Skip to content

Commit

Permalink
Merge pull request #314 from entur/improve/testcontainers-for-pubsub-…
Browse files Browse the repository at this point in the history
…emulator

Improve/testcontainers for pubsub emulator
  • Loading branch information
testower authored May 23, 2024
2 parents 3f6fc05 + 648a6ac commit 07df1c9
Show file tree
Hide file tree
Showing 14 changed files with 216 additions and 111 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,21 @@ see `src/main/java/no/entur/uttu/stopplace/spi/StopPlaceRegistry.java`.

Refer to `src/test/resources/fixtures/stopplace.xml` for an example of a NeTEx file with stop places.

## Optional export notification message

If you want to notify an external system about a NeTEx file export, you can
provide an implementation of the `MessagingService` interface –– see
`src/main/java/no/entur/uttu/export/messaging/spi/MessagingService.java`.

The default MessagingService implementation is a noop.

## Disable Google PubSub autoconfiguration

If you don't use Google PubSub, sett this property:

# This property is needed to avoid pubsub autoconfiguration
spring.cloud.gcp.pubsub.enabled=false

## Running locally
### Build
To build the project from source, you need Java 21 and Maven 3.
Expand Down
11 changes: 10 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@

<properties>
<java.version>21</java.version>
<entur.google.pubsub.emulator.download.skip>false</entur.google.pubsub.emulator.download.skip>
<entur.google.pubsub.emulator.download.skip>true</entur.google.pubsub.emulator.download.skip>

<entur.helpers.version>2.21</entur.helpers.version>

Expand Down Expand Up @@ -308,6 +308,15 @@
<version>1.19.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>gcloud</artifactId>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/*
* Licensed under the EUPL, Version 1.2 or – as soon they will be approved by
* the European Commission - subsequent versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* https://joinup.ec.europa.eu/software/page/eupl
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the Licence is distributed on an "AS IS" basis,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Licence for the specific language governing permissions and
* limitations under the Licence.
*
*/

package no.entur.uttu.ext.entur.export.messaging;

import com.google.api.gax.core.CredentialsProvider;
import com.google.api.gax.core.NoCredentialsProvider;
import com.google.cloud.spring.pubsub.core.PubSubTemplate;
import com.google.cloud.spring.pubsub.core.subscriber.PubSubSubscriberTemplate;
import com.google.pubsub.v1.PubsubMessage;
import java.nio.charset.StandardCharsets;
import java.util.List;
import no.entur.uttu.UttuIntegrationTest;
import no.entur.uttu.export.messaging.spi.MessagingService;
import org.entur.pubsub.base.EnturGooglePubSubAdmin;
import org.junit.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.PubSubEmulatorContainer;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;

@Testcontainers
@ActiveProfiles({ "test", "entur-pubsub-messaging-service" })
public class EnturPubSubMessagingServiceTest extends UttuIntegrationTest {

public static final String TEST_CODESPACE = "rut";

public static final String TEST_EXPORT_FILE_NAME = "netex.zip";
private static PubSubEmulatorContainer pubsubEmulator;

@Autowired
private MessagingService messagingService;

@Autowired
private PubSubTemplate pubSubTemplate;

@Autowired
PubSubSubscriberTemplate subscriberTemplate;

@Autowired
private EnturGooglePubSubAdmin enturGooglePubSubAdmin;

@Value("${export.notify.queue.name:FlexibleLinesExportQueue}")
private String queueName;

@DynamicPropertySource
static void emulatorProperties(DynamicPropertyRegistry registry) {
registry.add(
"spring.cloud.gcp.pubsub.emulator-host",
pubsubEmulator::getEmulatorEndpoint
);
registry.add("spring.cloud.gcp.pubsub.enabled", () -> true);
registry.add("spring.cloud.gcp.project-id", () -> "uttu-gcp-test-project");
registry.add("spring.cloud.gcp.pubsub.project-id", () -> "uttu-gcp-test-project");
registry.add("export.notify.enabled", () -> true);
registry.add("export.notify.queue.name", () -> "FlexibleLinesExportQueue");
}

@BeforeClass
public static void init() {
pubsubEmulator =
new PubSubEmulatorContainer(
DockerImageName.parse("gcr.io/google.com/cloudsdktool/cloud-sdk:emulators")
);
pubsubEmulator.start();
}

@AfterClass
public static void tearDown() {
pubsubEmulator.stop();
}

@Before
public void setup() {
enturGooglePubSubAdmin.createSubscriptionIfMissing(queueName);
}

@After
public void teardown() {
enturGooglePubSubAdmin.deleteAllSubscriptions();
}

// By default, autoconfiguration will initialize application default credentials.
// For testing purposes, don't use any credentials. Bootstrap w/ NoCredentialsProvider.
@TestConfiguration
static class PubSubEmulatorConfiguration {

@Bean
CredentialsProvider googleCredentials() {
return NoCredentialsProvider.create();
}
}

@Test
public void testNotifyExport() {
messagingService.notifyExport(TEST_CODESPACE, TEST_EXPORT_FILE_NAME);

List<PubsubMessage> messages = pubSubTemplate.pullAndAck(queueName, 1, false);
Assert.assertEquals(1, messages.size());
PubsubMessage pubsubMessage = messages.get(0);
String codespace = pubsubMessage
.getAttributesMap()
.get(EnturPubSubMessagingService.HEADER_CHOUETTE_REFERENTIAL);
Assert.assertEquals("rb_" + TEST_CODESPACE, codespace);
Assert.assertEquals(
TEST_EXPORT_FILE_NAME,
pubsubMessage.getData().toString(StandardCharsets.UTF_8)
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package no.entur.uttu.ext.entur.config;

import org.entur.pubsub.base.config.GooglePubSubConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Profile;

@Configuration
@Profile("entur-pubsub-messaging-service")
@Import(GooglePubSubConfig.class)
public class EnturConfiguration {}
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package no.entur.uttu.export.messaging;
package no.entur.uttu.ext.entur.export.messaging;

import com.google.cloud.spring.pubsub.core.PubSubTemplate;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import no.entur.uttu.config.Context;
import no.entur.uttu.export.messaging.spi.MessagingService;
import no.entur.uttu.util.ExportUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Component
public class PubSubMessagingService implements MessagingService {
@Profile("entur-pubsub-messaging-service")
public class EnturPubSubMessagingService implements MessagingService {

public static final String HEADER_CHOUETTE_REFERENTIAL =
"RutebankenChouetteReferential";
Expand All @@ -29,7 +32,7 @@ public class PubSubMessagingService implements MessagingService {
@Value("${export.notify.queue.name:FlexibleLinesExportQueue}")
private String queueName;

public PubSubMessagingService(PubSubTemplate pubSubTemplate) {
public EnturPubSubMessagingService(PubSubTemplate pubSubTemplate) {
this.pubSubTemplate = pubSubTemplate;
}

Expand Down
3 changes: 0 additions & 3 deletions src/main/java/no/entur/uttu/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,15 @@

import no.entur.uttu.model.Provider;
import no.entur.uttu.repository.generic.ProviderEntityRepositoryImpl;
import org.entur.pubsub.base.config.GooglePubSubConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication(exclude = { UserDetailsServiceAutoConfiguration.class })
@Import(GooglePubSubConfig.class)
@EnableJpaRepositories(
basePackages = { "no.entur.uttu.repository" },
repositoryBaseClass = ProviderEntityRepositoryImpl.class
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/no/entur/uttu/export/ExportService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.List;
import no.entur.uttu.error.codedexception.CodedIllegalArgumentException;
import no.entur.uttu.export.linestatistics.ExportedLineStatisticsService;
import no.entur.uttu.export.messaging.MessagingService;
import no.entur.uttu.export.messaging.spi.MessagingService;
import no.entur.uttu.export.netex.DataSetProducer;
import no.entur.uttu.export.netex.NetexExporter;
import no.entur.uttu.model.Line;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package no.entur.uttu.export.messaging;

import no.entur.uttu.export.messaging.spi.MessagingService;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.stereotype.Component;

/**
* The default implementation is a noop operation
*/
@Component
@ConditionalOnMissingBean(
value = MessagingService.class,
ignored = NoopMessagingService.class
)
public class NoopMessagingService implements MessagingService {

@Override
public void notifyExport(String codespace, String filename) {
// intentionally empty
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package no.entur.uttu.export.messaging.spi;

/**
* Represents a service which can send a notification to an external system about an export
*/
public interface MessagingService {
/**
* Notify about export
* @param codespace The codespace of the provider
* @param filename The filename for this export
*/
void notifyExport(String codespace, String filename);
}
2 changes: 1 addition & 1 deletion src/test/java/no/entur/uttu/UttuIntegrationTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = UttuTestApp.class
)
@ActiveProfiles({ "google-pubsub-emulator", "test" })
@ActiveProfiles({ "test" })
@EnableAspectJAutoProxy(proxyTargetClass = true)
public abstract class UttuIntegrationTest {

Expand Down
3 changes: 0 additions & 3 deletions src/test/java/no/entur/uttu/UttuTestApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@

import no.entur.uttu.repository.generic.ProviderEntityRepositoryImpl;
import no.entur.uttu.security.UttuSecurityConfiguration;
import org.entur.pubsub.base.config.GooglePubSubConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.Import;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@Import(GooglePubSubConfig.class)
@EnableJpaRepositories(
basePackages = { "no.entur.uttu.repository" },
repositoryBaseClass = ProviderEntityRepositoryImpl.class
Expand Down

This file was deleted.

Loading

0 comments on commit 07df1c9

Please sign in to comment.