Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/docker_publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:
servers: '[{ "id": "github", "username": "${{ secrets.DCSA_USER }}", "password": "${{ secrets.DCSA_PACKAGES_PAT }}" }]'

- name: maven build
run: mvn -B package --file pom.xml
run: mvn -B package -Dchangelist=-RELEASE


# Build and push Docker image
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/docker_publish_bug_fix_test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: DO NOT APPROVE A PR WIT THIS CI FILE

on:
push:
branches:
- DDT-1284

env:
# Use docker.io for Docker Hub if empty
REGISTRY: ghcr.io
# github.repository as <account>/<repo>
IMAGE_NAME: ${{ github.repository }}

jobs:
build:

runs-on: ubuntu-latest
permissions:
contents: read
packages: write

steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: recursive

- name: Set up Java JDK
uses: actions/setup-java@v2
with:
distribution: 'temurin'
java-version: 17
cache: 'maven'

- name: maven-settings-xml-action
uses: whelk-io/maven-settings-xml-action@v12
with:
repositories: '[{ "id": "github", "name": "DCSA Backend repo", "url": "https://maven.pkg.github.com/dcsaorg/DCSA-Core", "releases": { "enabled": "true" }, "snapshots": { "enabled": "true" } }]'
servers: '[{ "id": "github", "username": "${{ secrets.DCSA_USER }}", "password": "${{ secrets.DCSA_PACKAGES_PAT }}" }]'

- name: maven build
run: mvn -B package -Dchangelist=-RELEASE


# Build and push Docker image
# https://github.com/marketplace/actions/docker-build-push-action
- name: Build and push Docker image
uses: mr-smithers-excellent/docker-build-push@v5
with:
image: dcsa-jit
tags: v1.2.0-beta1-rc2-latest
registry: ghcr.io
githubOrg: dcsaorg
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
7 changes: 4 additions & 3 deletions .github/workflows/master.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,20 @@ jobs:
- name: Fetch Backend Status
run: |
sleep 10
status=$(curl -s http://localhost:9090/v1/actuator/health | jq -r '.status')
url=http://localhost:9090/jit/v1/actuator/health
status=$(curl -s "${url}" | jq -r '.status')
retries=12

while [[ "$status" != "UP" ]] && [[ $retries -gt 0 ]]; do
echo "Status is '$status' - waiting 5 secs ($retries retries left)"
sleep 5
retries=$((retries - 1))
status=$(curl -s http://localhost:9090/v1/actuator/health | jq -r '.status')
status=$(curl -s "${url}" | jq -r '.status')
done

echo "Final status is '$status'"
if [[ "$status" != "UP" ]]; then
curl -v http://localhost:9090/v1/actuator/health || :
curl -v "${url}" || :
docker ps || :
docker logs dcsa-jit_dcsa-jit_1 || :
exit 1
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publishRelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
IFS='-'
read -ra PROJ_TAG <<<"${{ steps.get-version.outputs.version }}"

if [[ "${{ steps.get-changelist.outputs.info }}" == "-RELEASE" && "${PROJ_TAG[1]}" == "RELEASE" ]];
if [[ "${{ steps.get-changelist.outputs.info }}" == "-RELEASE" && "${PROJ_TAG[-1]}" == "RELEASE" ]];
then
echo "Version is RELEASE"
else
Expand Down
9 changes: 6 additions & 3 deletions jit-application/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ dcsa:
version: 1.1.0
webui:
baseUrl: "NOT_SPECIFIED"
sync:
pollFrequency: ${SYNC_POLL_FREQUENCY:60000}
maxMessagesPerPoll: ${SYNC_MAX_MESSAGES_PER_POLL:10}
email:
from: noreply@dcsa.org
timezone: "NOT_SPECIFIED"
Expand All @@ -22,8 +25,8 @@ camel:
max-redeliveries: 3
redelivery-delay: 10000
route:
pending-email-notification: "jpa:org.dcsa.jit.persistence.entity.PendingEmailNotification?namedQuery=PendingEmailNotification.nextPendingEmailNotifications&delay=60000&maximumResults=10"
outbox-msg: "jpa:org.dcsa.jit.persistence.entity.OutboxMessage?namedQuery=poll-outbox-messages&delay=60000&transacted=true&maximumResults=10"
pending-email-notification: "jpa:org.dcsa.jit.persistence.entity.PendingEmailNotification?namedQuery=PendingEmailNotification.nextPendingEmailNotifications&delay=${dcsa.sync.pollFrequency}&maximumResults=${dcsa.sync.maxMessagesPerPoll}"
outbox-msg: "jpa:org.dcsa.jit.persistence.entity.OutboxMessage?namedQuery=poll-outbox-messages&delay=${dcsa.sync.pollFrequency}&transacted=true&maximumResults=${dcsa.sync.maxMessagesPerPoll}"
emit-message: direct:emit-message
oidc: direct:OIDC
timestamp-notify: direct:timestamp-notification
Expand Down Expand Up @@ -75,7 +78,7 @@ spring:

server:
port: 9090
servlet.context-path: /v1
servlet.context-path: /jit/v1
error:
include-binding-errors: on_param
include-message: always
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ class OperationsEventControllerTest {
@MockBean ServiceRepository serviceRepository;
@MockBean OperationsEventRepository operationsEventRepository;
@MockBean UnLocationRepository unLocationRepository;
@MockBean UnmappedEventRepository unmappedEventRepository;
@MockBean SMDGDelayReasonRepository smdgDelayReasonRepository;
@MockBean PendingEmailNotificationRepository pendingEmailNotificationRepository;
@MockBean OpsEventTimestampDefinitionRepository opsEventTimestampDefinitionRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ class SecurityFlowIT {
@MockBean TimestampDefinitionRepository timestampDefinitionRepository;
@MockBean TransportCallRepository transportCallRepository;
@MockBean UnLocationRepository unLocationRepository;
@MockBean UnmappedEventRepository unmappedEventRepository;
@MockBean VesselRepository vesselRepository;
@MockBean TimestampInfoRepository timestampInfoRepository;
@MockBean SMDGDelayReasonRepository smdgDelayReasonRepository;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@
public class RestAssuredConfigurator {

// API endpoints
public static final String EVENT_SUBSCRIPTIONS = "/v1/event-subscriptions";
public static final String EVENTS = "/v1/events";
public static final String TIMESTAMPS = "/v1/timestamps";
public static final String EVENTS = "/jit/v1/events";
public static final String TIMESTAMPS = "/jit/v1/timestamps";

public void initialize() {
var properties = IntegrationTestsProperties.getInstance();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public static void initializeRestAssured() {
public void testHealth() {
given()
.contentType("application/json")
.get("/v1/actuator/health")
.get("/jit/v1/actuator/health")
.then()
.assertThat()
.statusCode(200)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static void initializeRestAssured() {
public void testOperationsEventWithoutQueryParameters() {
given()
.contentType(ContentType.JSON)
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -52,7 +52,7 @@ public void testOperationsEventWithLimit1() {
given()
.contentType(ContentType.JSON)
.queryParam("limit", 1)
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -66,7 +66,7 @@ public void testOperationsEventWithLimit2() {
given()
.contentType(ContentType.JSON)
.queryParam("limit", 2)
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -80,7 +80,7 @@ public void testOperationsEventWithTransportCallIdQueryParameter() {
given()
.contentType(ContentType.JSON)
.queryParam("transportCallID", "TC-REF-08_03-A")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -100,7 +100,7 @@ public void testWithUnLocationCodeQueryParameter() {
given()
.contentType(ContentType.JSON)
.queryParam("UNLocationCode", "USNYC")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -115,7 +115,7 @@ public void testWithVeselImoNumberQueryParameter() {
given()
.contentType(ContentType.JSON)
.queryParam("vesselIMONumber", "9811000")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -130,7 +130,7 @@ public void testWithOperationsEventTypeCodeQueryParameter1() {
given()
.contentType(ContentType.JSON)
.queryParam("operationsEventTypeCode", "ARRI")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -144,7 +144,7 @@ public void testWithOperationsEventTypeCodeQueryParameter2() {
given()
.contentType(ContentType.JSON)
.queryParam("operationsEventTypeCode", "DEPA")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -158,7 +158,7 @@ public void testWithCarrierVoyageNumberQueryParameter() {
given()
.contentType(ContentType.JSON)
.queryParam("carrierVoyageNumber", "A_carrier_voyage_number")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -172,7 +172,7 @@ public void testWithExportVoyageNumberQueryParameter() {
given()
.contentType(ContentType.JSON)
.queryParam("carrierExportVoyageNumber", "TNT1E")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -186,7 +186,7 @@ public void testWithCarrierServiceCodeQueryParameter1() {
given()
.contentType(ContentType.JSON)
.queryParam("carrierServiceCode", "TNT1")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand All @@ -200,7 +200,7 @@ public void testWithCarrierServiceCodeQueryParameter2() {
given()
.contentType(ContentType.JSON)
.queryParam("carrierServiceCode", "FE1")
.get("/v1/events")
.get("/jit/v1/events")
.then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,31 +100,28 @@ void timestampNotification() {
.redeliveryDelay("{{camel.redelivery-delay}}")
.useExponentialBackOff()
.backOffMultiplier(2)
.log("Timestamp request failed!")
.process(new DeadTimestampProcessor())
.to("jpa:org.dcsa.jit.persistence.entity.TimestampNotificationDead")
.end()
.setHeader("CamelHttpMethod", constant("POST"))
.setHeader("Content-Type", simple("application/json"))
.setHeader("Authorization", simple("${body}"))
.setBody(simple("${exchangeProperty.outboxMessage.payload}"))
.toD("${exchangeProperty.outboxMessage.messageRoutingRule.apiUrl}");
.toD("${exchangeProperty.outboxMessage.messageRoutingRule.apiUrl}")
.log("Successfully forwarded a timestamp to ${exchangeProperty.outboxMessage.messageRoutingRule.apiUrl}");
}

// inner class as its only required within TimestampRoutingService
static class DeadTimestampProcessor implements Processor {

@Override
public void process(Exchange exchange) throws Exception {
public void process(Exchange exchange) {
OutboxMessage outboxMessage = (OutboxMessage) exchange.getProperty("outboxMessage");
Exception cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Exception.class);
log.info("Failed to delivery timestamp: {} -> {} '{}'", outboxMessage, cause.getClass().getName(), cause.getMessage());
exchange
.getIn()
.setBody(
TimestampNotificationDead.builder()
.messageRoutingRule(outboxMessage.getMessageRoutingRule())
.payload(outboxMessage.getPayload())
.latestDeliveryAttemptedDatetime(OffsetDateTime.now())
.build());
.setBody(TimestampNotificationDead.from(outboxMessage));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.dcsa.jit.persistence.entity;

import lombok.*;
import org.springframework.data.domain.Persistable;

import javax.persistence.*;
import java.util.UUID;
Expand All @@ -13,7 +14,7 @@
@Entity
@Table(name = "outbox_message")
@NamedQuery(name = "poll-outbox-messages", query = "SELECT om FROM OutboxMessage om")
public class OutboxMessage {
public class OutboxMessage implements Persistable<UUID> {
@Id
@GeneratedValue
@Column(name = "id", nullable = false)
Expand All @@ -27,4 +28,21 @@ public class OutboxMessage {
@Column(name = "payload", nullable = false, columnDefinition = "TEXT")
private String
payload; // String as payload since persistence module should not import transfer-obj

@Transient
private boolean isNew;

public boolean isNew() {
return id == null || isNew;
}

public static OutboxMessage retry(TimestampNotificationDead dead) {
return OutboxMessage.builder()
.id(dead.getId())
.messageRoutingRule(dead.getMessageRoutingRule())
.payload(dead.getPayload())
.isNew(true)
.build();
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.dcsa.jit.persistence.entity;

import lombok.*;
import org.springframework.data.domain.Persistable;

import javax.persistence.*;
import java.time.OffsetDateTime;
Expand All @@ -13,7 +14,7 @@
@Setter(AccessLevel.PRIVATE)
@Entity
@Table(name = "timestamp_notification_dead")
public class TimestampNotificationDead {
public class TimestampNotificationDead implements Persistable<UUID> {

@Id
@GeneratedValue
Expand All @@ -30,4 +31,22 @@ public class TimestampNotificationDead {

@Column(name = "latest_delivery_attempted_datetime")
private OffsetDateTime latestDeliveryAttemptedDatetime;

@Transient
private boolean isNew;

public boolean isNew() {
return id == null || isNew;
}

public static TimestampNotificationDead from(OutboxMessage outboxMessage) {
return TimestampNotificationDead.builder()
// Preserve the ID to make tracking easier across fail-retry cycles.
.id(outboxMessage.getId())
.messageRoutingRule(outboxMessage.getMessageRoutingRule())
.payload(outboxMessage.getPayload())
.latestDeliveryAttemptedDatetime(OffsetDateTime.now())
.isNew(true)
.build();
}
}
Loading