Init
This commit is contained in:
81
.idea/compiler.xml
generated
81
.idea/compiler.xml
generated
@@ -35,6 +35,85 @@
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/antlr/antlr4-runtime/4.13.2/antlr4-runtime-4.13.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/net/bytebuddy/byte-buddy/1.17.8/byte-buddy-1.17.8.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/jboss/logging/jboss-logging/3.6.1.Final/jboss-logging-3.6.1.Final.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_core/2.28.0/error_prone_core-2.28.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_annotation/2.28.0/error_prone_annotation-2.28.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_type_annotations/2.28.0/error_prone_type_annotations-2.28.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_check_api/2.28.0/error_prone_check_api-2.28.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/io/github/java-diff-utils/java-diff-utils/4.12/java-diff-utils-4.12.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/github/kevinstern/software-and-algorithms/1.0/software-and-algorithms-1.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/github/ben-manes/caffeine/caffeine/3.0.5/caffeine-3.0.5.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/inject/guice/5.1.0/guice-5.1.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/aopalliance/aopalliance/1.0/aopalliance-1.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/pcollections/pcollections/4.0.1/pcollections-4.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/guava/guava/32.1.1-jre/guava-32.1.1-jre.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/auto/auto-common/1.2.2/auto-common-1.2.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/io/github/eisop/dataflow-errorprone/3.41.0-eisop1/dataflow-errorprone-3.41.0-eisop1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/auto/value/auto-value-annotations/1.9/auto-value-annotations-1.9.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_annotations/2.28.0/error_prone_annotations-2.28.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/protobuf/protobuf-java/3.19.6/protobuf-java-3.19.6.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/auto/service/auto-service-annotations/1.0.1/auto-service-annotations-1.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/uber/nullaway/nullaway/0.11.0/nullaway-0.11.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/checkerframework/dataflow-nullaway/3.43.0/dataflow-nullaway-3.43.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_core/2.37.0/error_prone_core-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_annotation/2.37.0/error_prone_annotation-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_check_api/2.37.0/error_prone_check_api-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/googlejavaformat/google-java-format/1.24.0/google-java-format-1.24.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_annotations/2.37.0/error_prone_annotations-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/protobuf/protobuf-java/3.25.5/protobuf-java-3.25.5.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/uber/nullaway/nullaway/0.13.1/nullaway-0.13.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/checkerframework/dataflow-nullaway/3.53.0/dataflow-nullaway-3.53.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/projectlombok/lombok/1.18.42/lombok-1.18.42.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_core/2.37.0/error_prone_core-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_annotation/2.37.0/error_prone_annotation-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_check_api/2.37.0/error_prone_check_api-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/io/github/java-diff-utils/java-diff-utils/4.12/java-diff-utils-4.12.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/github/kevinstern/software-and-algorithms/1.0/software-and-algorithms-1.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/github/ben-manes/caffeine/caffeine/3.0.5/caffeine-3.0.5.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/googlejavaformat/google-java-format/1.24.0/google-java-format-1.24.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/pcollections/pcollections/4.0.1/pcollections-4.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/guava/guava/32.1.1-jre/guava-32.1.1-jre.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/guava/listenablefuture/9999.0-empty-to-avoid-conflict-with-guava/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/checkerframework/checker-qual/3.33.0/checker-qual-3.33.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/j2objc/j2objc-annotations/2.8/j2objc-annotations-2.8.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/auto/auto-common/1.2.2/auto-common-1.2.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/io/github/eisop/dataflow-errorprone/3.41.0-eisop1/dataflow-errorprone-3.41.0-eisop1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/auto/value/auto-value-annotations/1.9/auto-value-annotations-1.9.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/errorprone/error_prone_annotations/2.37.0/error_prone_annotations-2.37.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/protobuf/protobuf-java/3.25.5/protobuf-java-3.25.5.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/google/auto/service/auto-service-annotations/1.0.1/auto-service-annotations-1.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/jspecify/jspecify/1.0.0/jspecify-1.0.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/javax/inject/javax.inject/1/javax.inject-1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/uber/nullaway/nullaway/0.13.1/nullaway-0.13.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/checkerframework/dataflow-nullaway/3.53.0/dataflow-nullaway-3.53.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/hibernate/orm/hibernate-processor/7.2.4.Final/hibernate-processor-7.2.4.Final.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/hibernate/orm/hibernate-core/7.2.4.Final/hibernate-core-7.2.4.Final.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/persistence/jakarta.persistence-api/3.2.0/jakarta.persistence-api-3.2.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/transaction/jakarta.transaction-api/2.0.1/jakarta.transaction-api-2.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/fasterxml/classmate/1.7.1/classmate-1.7.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/inject/jakarta.inject-api/2.0.1/jakarta.inject-api-2.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/hibernate/models/hibernate-models/1.0.1/hibernate-models-1.0.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/io/smallrye/jandex/3.3.2/jandex-3.3.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/xml/bind/jakarta.xml.bind-api/4.0.4/jakarta.xml.bind-api-4.0.4.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/activation/jakarta.activation-api/2.1.4/jakarta.activation-api-2.1.4.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/glassfish/jaxb/jaxb-runtime/4.0.6/jaxb-runtime-4.0.6.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/glassfish/jaxb/jaxb-core/4.0.6/jaxb-core-4.0.6.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/eclipse/angus/angus-activation/2.0.3/angus-activation-2.0.3.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/glassfish/jaxb/txw2/4.0.6/txw2-4.0.6.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/com/sun/istack/istack-commons-runtime/4.1.2/istack-commons-runtime-4.1.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/validation/jakarta.validation-api/3.1.1/jakarta.validation-api-3.1.1.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/jakarta/annotation/jakarta.annotation-api/3.0.0/jakarta.annotation-api-3.0.0.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/antlr/antlr4-runtime/4.13.2/antlr4-runtime-4.13.2.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/net/bytebuddy/byte-buddy/1.17.8/byte-buddy-1.17.8.jar" />
|
||||
<entry name="$USER_HOME$/.m2/peak-repo/org/jboss/logging/jboss-logging/3.6.1.Final/jboss-logging-3.6.1.Final.jar" />
|
||||
</processorPath>
|
||||
<module name="peakup-backend" />
|
||||
</profile>
|
||||
@@ -45,7 +124,7 @@
|
||||
</component>
|
||||
<component name="JavacSettings">
|
||||
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
|
||||
<module name="peakup-backend" options="" />
|
||||
<module name="peakup-backend" options="-XDcompilePolicy=simple -XDshould-stop.ifError=FLOW "-Xplugin:ErrorProne -Xep:NullAway:ERROR -XepOpt:NullAway:AnnotatedPackages=com.peakup -XepOpt:NullAway:TreatGeneratedAsUnannotated=true" -Xpkginfo:always" />
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
7
.idea/misc.xml
generated
7
.idea/misc.xml
generated
@@ -1,5 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EntryPointsManager">
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="jakarta.enterprise.context.ApplicationScoped" />
|
||||
</list>
|
||||
</component>
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="Quarkus" url="file://$PROJECT_DIR$" />
|
||||
@@ -13,5 +18,5 @@
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_25" project-jdk-name="temurin-25" project-jdk-type="JavaSDK" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_21" project-jdk-name="temurin-21" project-jdk-type="JavaSDK" />
|
||||
</project>
|
||||
10
peakup-backend/.mvn/jvm.config
Normal file
10
peakup-backend/.mvn/jvm.config
Normal file
@@ -0,0 +1,10 @@
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
|
||||
--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
|
||||
--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
|
||||
--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
|
||||
7
peakup-backend/lombok.config
Normal file
7
peakup-backend/lombok.config
Normal file
@@ -0,0 +1,7 @@
|
||||
config.stopBubbling = true
|
||||
|
||||
lombok.addLombokGeneratedAnnotation = true
|
||||
|
||||
|
||||
lombok.copyableAnnotations += com.peakup.common.annotation.Nullable
|
||||
lombok.copyableAnnotations += com.peakup.common.annotation.NonNull
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
<properties>
|
||||
<compiler-plugin.version>3.15.0</compiler-plugin.version>
|
||||
<maven.compiler.release>25</maven.compiler.release>
|
||||
<maven.compiler.source>25</maven.compiler.source>
|
||||
<maven.compiler.target>25</maven.compiler.target>
|
||||
<maven.compiler.release>21</maven.compiler.release>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<lombok.version>1.18.42</lombok.version>
|
||||
<jsr305.version>3.0.2</jsr305.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
@@ -113,6 +113,7 @@
|
||||
<version>${jsr305.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.quarkus</groupId>
|
||||
<artifactId>quarkus-junit5</artifactId>
|
||||
@@ -148,12 +149,31 @@
|
||||
<version>${compiler-plugin.version}</version>
|
||||
<configuration>
|
||||
<release>${maven.compiler.release}</release>
|
||||
<showWarnings>true</showWarnings>
|
||||
<compilerArgs>
|
||||
<arg>-XDcompilePolicy=simple</arg>
|
||||
<arg>-XDshould-stop.ifError=FLOW</arg>
|
||||
<arg>-Xplugin:ErrorProne -Xep:NullAway:ERROR -XepOpt:NullAway:AnnotatedPackages=com.peakup
|
||||
-XepOpt:NullAway:TreatGeneratedAsUnannotated=true
|
||||
</arg>
|
||||
<arg>-Xpkginfo:always</arg>
|
||||
</compilerArgs>
|
||||
<annotationProcessorPaths>
|
||||
<path>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${lombok.version}</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.google.errorprone</groupId>
|
||||
<artifactId>error_prone_core</artifactId>
|
||||
<version>2.37.0</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>com.uber.nullaway</groupId>
|
||||
<artifactId>nullaway</artifactId>
|
||||
<version>0.13.1</version>
|
||||
</path>
|
||||
<path>
|
||||
<groupId>org.hibernate.orm</groupId>
|
||||
<artifactId>hibernate-jpamodelgen</artifactId>
|
||||
@@ -175,7 +195,7 @@
|
||||
<configuration>
|
||||
<rules>
|
||||
<requireJavaVersion>
|
||||
<version>[25,26)</version>
|
||||
<version>[21,22)</version>
|
||||
</requireJavaVersion>
|
||||
</rules>
|
||||
<fail>true</fail>
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.peakup.activity.model.Activity;
|
||||
import com.peakup.activity.model.Activity_;
|
||||
import com.peakup.activity.model.OriginEnum;
|
||||
import com.peakup.dao.AbstractDAO;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
@@ -17,7 +18,7 @@ public class ActivityDAO extends AbstractDAO<Activity> {
|
||||
return Activity.class;
|
||||
}
|
||||
|
||||
public Activity getLatestActivity(Long athleteId) {
|
||||
public @Nullable Activity getLatestActivity(Long athleteId) {
|
||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
// Wir definieren, dass das Ergebnis eine Activity-Entität sein soll
|
||||
CriteriaQuery<Activity> cq = cb.createQuery(Activity.class);
|
||||
@@ -35,7 +36,7 @@ public class ActivityDAO extends AbstractDAO<Activity> {
|
||||
.orElse(null); // Gibt null zurück, wenn der Athlet noch keine Aktivitäten hat
|
||||
}
|
||||
|
||||
public Activity getActivity(String originId, OriginEnum originEnum) {
|
||||
public @Nullable Activity getActivity(String originId, OriginEnum originEnum) {
|
||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<Activity> cq = cb.createQuery(Activity.class);
|
||||
Root<Activity> root = cq.from(Activity.class);
|
||||
|
||||
@@ -8,14 +8,12 @@ import jakarta.persistence.Entity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Activity extends AbstractTimestampedEntity {
|
||||
|
||||
@@ -88,4 +86,10 @@ public class Activity extends AbstractTimestampedEntity {
|
||||
|
||||
@Column(name = "calories")
|
||||
public Double calories;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
public Activity() {
|
||||
// hibernate
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.peakup.activity.model.OriginEnum;
|
||||
import com.peakup.connector.strava.StravaClient;
|
||||
import com.peakup.connector.strava.StravaContext;
|
||||
import com.peakup.service.AbstractService;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
@@ -15,6 +16,8 @@ import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
|
||||
import static com.peakup.common.NullableUtils.defaultValue;
|
||||
|
||||
@lombok.extern.slf4j.Slf4j
|
||||
@ApplicationScoped
|
||||
public class ActivityService extends AbstractService<Activity, ActivityDAO> {
|
||||
@@ -28,6 +31,7 @@ public class ActivityService extends AbstractService<Activity, ActivityDAO> {
|
||||
StravaContext stravaContext;
|
||||
|
||||
@RestClient
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
private StravaClient stravaClient;
|
||||
|
||||
@Override
|
||||
@@ -37,7 +41,7 @@ public class ActivityService extends AbstractService<Activity, ActivityDAO> {
|
||||
|
||||
|
||||
@Transactional
|
||||
protected Activity getLatestActivity(Long athleteId) {
|
||||
protected @Nullable Activity getLatestActivity(Long athleteId) {
|
||||
return activityDAO.getLatestActivity(athleteId);
|
||||
}
|
||||
|
||||
@@ -90,11 +94,11 @@ public class ActivityService extends AbstractService<Activity, ActivityDAO> {
|
||||
activity.originEnum = origin;
|
||||
|
||||
// Basis Infos
|
||||
activity.name = stravaActivity.name;
|
||||
activity.type = stravaActivity.type;
|
||||
activity.sportType = stravaActivity.sport_type;
|
||||
activity.deviceName = stravaActivity.device_name;
|
||||
activity.timezone = stravaActivity.timezone;
|
||||
activity.name = defaultValue(stravaActivity.name);
|
||||
activity.type = defaultValue(stravaActivity.type);
|
||||
activity.sportType = defaultValue(stravaActivity.sport_type);
|
||||
activity.deviceName = defaultValue(stravaActivity.device_name);
|
||||
activity.timezone = defaultValue(stravaActivity.timezone);
|
||||
|
||||
// Zeit-Handling (ISO-8601 String zu Instant)
|
||||
if (stravaActivity.start_date != null) {
|
||||
@@ -102,26 +106,26 @@ public class ActivityService extends AbstractService<Activity, ActivityDAO> {
|
||||
}
|
||||
|
||||
// Metriken (Distanz & Zeit)
|
||||
activity.distanceM = stravaActivity.distance;
|
||||
activity.movingTimeS = stravaActivity.moving_time;
|
||||
activity.elapsedTimeS = stravaActivity.elapsed_time;
|
||||
activity.totalElevationGainM = stravaActivity.total_elevation_gain;
|
||||
activity.distanceM = defaultValue(stravaActivity.distance);
|
||||
activity.movingTimeS = defaultValue(stravaActivity.moving_time);
|
||||
activity.elapsedTimeS = defaultValue(stravaActivity.elapsed_time);
|
||||
activity.totalElevationGainM = defaultValue(stravaActivity.total_elevation_gain);
|
||||
|
||||
// Geschwindigkeit
|
||||
activity.averageSpeedMps = stravaActivity.average_speed;
|
||||
activity.maxSpeedMps = stravaActivity.max_speed;
|
||||
activity.averageSpeedMps = defaultValue(stravaActivity.average_speed);
|
||||
activity.maxSpeedMps = defaultValue(stravaActivity.max_speed);
|
||||
|
||||
// Herzfrequenz
|
||||
activity.averageHeartrateBpm = stravaActivity.average_heartrate;
|
||||
activity.maxHeartrateBPM = stravaActivity.max_heartrate;
|
||||
activity.averageHeartrateBpm = defaultValue(stravaActivity.average_heartrate);
|
||||
activity.maxHeartrateBPM = defaultValue(stravaActivity.max_heartrate);
|
||||
|
||||
// Power & Arbeit
|
||||
activity.averagePowerWatt = stravaActivity.average_watts;
|
||||
activity.maxPowerWatt = stravaActivity.max_watts;
|
||||
activity.normalizedPowerWatt = stravaActivity.weighted_average_watts; // Strava's NP
|
||||
activity.totalWorkKJ = stravaActivity.kilojoules;
|
||||
activity.averagePowerWatt = defaultValue(stravaActivity.average_watts);
|
||||
activity.maxPowerWatt = defaultValue(stravaActivity.max_watts);
|
||||
activity.normalizedPowerWatt = defaultValue(stravaActivity.weighted_average_watts); // Strava's NP
|
||||
activity.totalWorkKJ = defaultValue(stravaActivity.kilojoules);
|
||||
|
||||
activity.averageCadenceRPM = stravaActivity.average_cadence;
|
||||
activity.calories = stravaActivity.calories;
|
||||
activity.averageCadenceRPM = defaultValue(stravaActivity.average_cadence);
|
||||
activity.calories = defaultValue(stravaActivity.calories);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,24 +6,27 @@ import jakarta.persistence.Entity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class Athlete extends AbstractTimestampedEntity {
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String firstName;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String lastName;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private Double weight;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private SexEnum sex;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
public Athlete() {
|
||||
// hibernate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,23 @@
|
||||
package com.peakup.common;
|
||||
|
||||
public class Assert {
|
||||
private Assert() {}
|
||||
import jakarta.annotation.Nullable;
|
||||
|
||||
public static void isTrue(boolean expression, String message) {
|
||||
public class Assert {
|
||||
private Assert() {
|
||||
}
|
||||
|
||||
public static void isTrue(boolean expression, @Nullable String message) {
|
||||
if (!expression) {
|
||||
throw new AssertionError(message);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public static void isTrue(boolean expression) {
|
||||
isTrue(expression, null);
|
||||
}
|
||||
|
||||
public static void notNull(Object object, String message) {
|
||||
public static void notNull(@Nullable Object object, @Nullable String message) {
|
||||
if (object == null) {
|
||||
throw new AssertionError(message);
|
||||
}
|
||||
@@ -23,15 +27,15 @@ public class Assert {
|
||||
notNull(object, null);
|
||||
}
|
||||
|
||||
public static void isEqual(Object objectA, Object objectB) {
|
||||
public static void isEqual(@Nullable Object objectA, @Nullable Object objectB) {
|
||||
if (objectA == objectB) {
|
||||
return;
|
||||
}
|
||||
if (objectA == null || objectB == null ) {
|
||||
throw new AssertionError("ObjectA is "+objectA +" and ObjectB is "+objectB);
|
||||
if (objectA == null || objectB == null) {
|
||||
throw new AssertionError("ObjectA is " + objectA + " and ObjectB is " + objectB);
|
||||
}
|
||||
if (!objectA.equals(objectB)) {
|
||||
throw new AssertionError("ObjectA is "+objectA +" and ObjectB is "+objectB);
|
||||
throw new AssertionError("ObjectA is " + objectA + " and ObjectB is " + objectB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.peakup.common;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
|
||||
public class NullableUtils {
|
||||
private NullableUtils() {
|
||||
}
|
||||
|
||||
public static String defaultValue(@Nullable String value) {
|
||||
return value == null ? "" : value;
|
||||
}
|
||||
|
||||
public static double defaultValue(@Nullable Double value) {
|
||||
return value == null ? 0 : value;
|
||||
}
|
||||
|
||||
public static int defaultValue(@Nullable Integer value) {
|
||||
return value == null ? 0 : value;
|
||||
}
|
||||
|
||||
public static long defaultValue(@Nullable Long value) {
|
||||
return value == null ? 0L : value;
|
||||
}
|
||||
}
|
||||
@@ -2,26 +2,23 @@ package com.peakup.common;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@ApplicationScoped
|
||||
public class TokenCache {
|
||||
|
||||
private Cache<Long, String> cache = Caffeine.newBuilder()
|
||||
private final Cache<Long, String> cache = Caffeine.newBuilder()
|
||||
.expireAfterWrite(10, TimeUnit.SECONDS)
|
||||
.maximumSize(100)
|
||||
.<Long, String>build();
|
||||
.build();
|
||||
|
||||
public String getBearerToken(Long athleteId) {
|
||||
String token = cache.getIfPresent(athleteId);
|
||||
if (StringUtils.isEmpty(token) ) {
|
||||
|
||||
}
|
||||
return token;
|
||||
public @Nullable String getBearerToken(Long athleteId) {
|
||||
String token = cache.getIfPresent(athleteId);
|
||||
return token;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.peakup.connector.strava;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.ws.rs.*;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
@@ -21,35 +22,41 @@ public interface StravaClient {
|
||||
@Path("/athlete/activities")
|
||||
List<Activity> getAthleteActivities(
|
||||
|
||||
@QueryParam("before") Long before,
|
||||
@QueryParam("before") @Nullable Long before,
|
||||
@QueryParam("after") Long after,
|
||||
@QueryParam("page") Integer page,
|
||||
@QueryParam("per_page") Integer perPage
|
||||
);
|
||||
|
||||
class Activity {
|
||||
public Long id;
|
||||
public String name;
|
||||
public String type;
|
||||
public String sport_type;
|
||||
public String start_date; // UTC ISO-8601
|
||||
public String start_date_local;
|
||||
public String timezone;
|
||||
public Double distance;
|
||||
public Long moving_time;
|
||||
public Long elapsed_time;
|
||||
public Double total_elevation_gain;
|
||||
public Double average_speed;
|
||||
public Double max_speed;
|
||||
public Double average_heartrate;
|
||||
public Double max_heartrate;
|
||||
public Double average_watts;
|
||||
public Double max_watts;
|
||||
public Double weighted_average_watts;// Normalized Power
|
||||
public Double average_cadence;
|
||||
public Double kilojoules;
|
||||
public Double calories;
|
||||
public String device_name;
|
||||
public @Nullable Long id;
|
||||
public @Nullable String name;
|
||||
public @Nullable String type;
|
||||
public @Nullable String sport_type;
|
||||
public @Nullable String start_date; // UTC ISO-8601
|
||||
@SuppressWarnings("unused")
|
||||
public @Nullable String start_date_local;
|
||||
public @Nullable String timezone;
|
||||
public @Nullable Double distance;
|
||||
public @Nullable Long moving_time;
|
||||
public @Nullable Long elapsed_time;
|
||||
public @Nullable Double total_elevation_gain;
|
||||
public @Nullable Double average_speed;
|
||||
public @Nullable Double max_speed;
|
||||
public @Nullable Double average_heartrate;
|
||||
public @Nullable Double max_heartrate;
|
||||
public @Nullable Double average_watts;
|
||||
public @Nullable Double max_watts;
|
||||
public @Nullable Double weighted_average_watts;// Normalized Power
|
||||
public @Nullable Double average_cadence;
|
||||
public @Nullable Double kilojoules;
|
||||
public @Nullable Double calories;
|
||||
public @Nullable String device_name;
|
||||
|
||||
@SuppressWarnings({"NullAway.Init", "unused"})
|
||||
private Activity() {
|
||||
// json
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.peakup.connector.strava;
|
||||
|
||||
import com.peakup.connector.strava.service.StravaConnectorService;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
|
||||
@@ -9,7 +8,6 @@ import jakarta.inject.Inject;
|
||||
@ApplicationScoped
|
||||
public class StravaContext {
|
||||
|
||||
|
||||
private static final ThreadLocal<Long> ATHLETE_ID = new ThreadLocal<>();
|
||||
|
||||
@Inject
|
||||
@@ -25,19 +23,7 @@ public class StravaContext {
|
||||
return stravaConnectorService.getToken(ATHLETE_ID.get(), currentTimeInSeconds);
|
||||
}
|
||||
|
||||
public String getTokenNull() {
|
||||
final String token = getTokenNull(null);
|
||||
return token;
|
||||
}
|
||||
|
||||
public @Nullable String getTokenNull(Long athleteId) {
|
||||
if (athleteId == null) {
|
||||
return null;
|
||||
}
|
||||
return getToken();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void clear() {
|
||||
ATHLETE_ID.remove();
|
||||
}
|
||||
|
||||
@@ -6,34 +6,37 @@ import jakarta.persistence.Entity;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Entity
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
public class StravaConnector extends AbstractTimestampedEntity {
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private Long athleteId; // loose coupling
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String stravaAthleteId;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String accessToken;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String refreshToken;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private long expiresAt;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String clientId;
|
||||
|
||||
@Column
|
||||
@Column(nullable = false)
|
||||
private String clientSecret;
|
||||
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
public StravaConnector() {
|
||||
// hibernate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@lombok.extern.slf4j.Slf4j
|
||||
@ApplicationScoped
|
||||
@@ -19,10 +20,12 @@ public class StravaConnectorService extends AbstractService<StravaConnector, Str
|
||||
|
||||
|
||||
@RestClient
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
StravaAuthClient stravaAuthClient;
|
||||
|
||||
|
||||
@Inject
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
StravaConnectorDAO stravaConnectorDAO;
|
||||
|
||||
|
||||
@@ -54,7 +57,10 @@ public class StravaConnectorService extends AbstractService<StravaConnector, Str
|
||||
log.info("The token for athlete {} has been expired for {} seconds.", stravaConnector.getAthleteId(), (currentTimeInSeconds - stravaConnector.getExpiresAt()));
|
||||
Map<String, Object> result = stravaAuthClient.refreshToken(stravaConnector.getClientId(), stravaConnector.getClientSecret(), "refresh_token", stravaConnector.getRefreshToken());
|
||||
Assert.isEqual(result.get("token_type"), "Bearer");
|
||||
update(stravaConnector.getId(), result.get("access_token").toString(), result.get("refresh_token").toString(), (Integer) result.get("expires_at"));
|
||||
update(Objects.requireNonNull(stravaConnector.getId()),
|
||||
Objects.requireNonNull(result.get("access_token")).toString(),
|
||||
Objects.requireNonNull(result.get("refresh_token")).toString(),
|
||||
Objects.requireNonNull((Integer) result.get("expires_at")));
|
||||
}
|
||||
return stravaConnector.getAccessToken();
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ package com.peakup.dao;
|
||||
import com.peakup.common.PersistenceException;
|
||||
import com.peakup.model.AbstractEntity;
|
||||
import com.peakup.model.AbstractEntity_;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.PersistenceContext;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
@@ -13,7 +13,8 @@ import java.util.List;
|
||||
|
||||
public abstract class AbstractDAO<T extends AbstractEntity> {
|
||||
|
||||
@PersistenceContext
|
||||
@Inject
|
||||
@SuppressWarnings("NullAway.Init")
|
||||
protected EntityManager em;
|
||||
|
||||
public T getById(long id) {
|
||||
@@ -38,6 +39,7 @@ public abstract class AbstractDAO<T extends AbstractEntity> {
|
||||
|
||||
protected abstract Class<T> getEntityClass();
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
protected EntityManager getEntityManager() {
|
||||
return em;
|
||||
}
|
||||
@@ -50,6 +52,7 @@ public abstract class AbstractDAO<T extends AbstractEntity> {
|
||||
}
|
||||
em.persist(entity); // nach persist ist entity attached
|
||||
}
|
||||
|
||||
public void update(T entity) {
|
||||
if (!em.contains(entity)) {
|
||||
throw new PersistenceException(
|
||||
@@ -58,6 +61,7 @@ public abstract class AbstractDAO<T extends AbstractEntity> {
|
||||
}
|
||||
// Änderungen werden automatisch von JPA übernommen
|
||||
}
|
||||
|
||||
public void delete(T entity) {
|
||||
if (!em.contains(entity)) {
|
||||
entity = em.merge(entity); // sichergehen, dass attached
|
||||
|
||||
@@ -4,6 +4,7 @@ package com.peakup.dao;
|
||||
import com.peakup.activity.model.ActivityTypeEnum;
|
||||
import com.peakup.activity.model.OriginEnum;
|
||||
import com.peakup.athlete.model.SexEnum;
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.AttributeConverter;
|
||||
import jakarta.persistence.Converter;
|
||||
|
||||
@@ -16,12 +17,12 @@ public abstract class AbstractEnumConverter<V extends PersistableEnum> implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer convertToDatabaseColumn(V attribute) {
|
||||
public @Nullable Integer convertToDatabaseColumn(@Nullable V attribute) {
|
||||
return (attribute != null) ? attribute.getKey() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V convertToEntityAttribute(Integer dbData) {
|
||||
public @Nullable V convertToEntityAttribute(@Nullable Integer dbData) {
|
||||
if (dbData == null) return null;
|
||||
return getEnumByKey(dbData);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.peakup.model;
|
||||
|
||||
import jakarta.annotation.Nullable;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
@@ -15,6 +16,6 @@ public abstract class AbstractEntity {
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "global_seq")
|
||||
@SequenceGenerator(name = "global_seq", sequenceName = "global_id_seq", allocationSize = 1)
|
||||
@Column(name = "ID")
|
||||
private Long id;
|
||||
private @Nullable Long id;
|
||||
|
||||
}
|
||||
|
||||
@@ -18,18 +18,15 @@ import java.time.Instant;
|
||||
@AllArgsConstructor
|
||||
public abstract class AbstractTimestampedEntity extends AbstractEntity {
|
||||
|
||||
@Column
|
||||
private Instant modifiedAt;
|
||||
@Column(nullable = false)
|
||||
private Instant modifiedAt = Instant.now();
|
||||
|
||||
@Column
|
||||
private Instant createdAt;
|
||||
@Column(nullable = false)
|
||||
private Instant createdAt = Instant.now();
|
||||
|
||||
@PrePersist
|
||||
@PreUpdate
|
||||
public void updateModifiedAt() {
|
||||
modifiedAt = Instant.now();
|
||||
if (createdAt == null) {
|
||||
createdAt = Instant.now();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user