Skip to content

Commit

Permalink
Add failFast parameter to getExchangeRate to address issue JavaMo…
Browse files Browse the repository at this point in the history
…ney#385

This commit introduces a `failFast` parameter to the `getExchangeRate` method in the `CompoundRateProvider` class to work around the limitations described in issue JavaMoney#385.

The `failFast` parameter helps mitigate the problem by allowing the caller to specify whether the method should return immediately on failure. Due to current API constraints, we cannot modify the `getExchangeRate` signature in the `ExchangeRateProvider` interface without causing breaking changes.
  • Loading branch information
sernamar committed Sep 1, 2024
1 parent a61917b commit 69d0373
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 6 deletions.
7 changes: 7 additions & 0 deletions moneta-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.javamoney</groupId>
<artifactId>moneta</artifactId>
<version>1.4.4</version>
<type>pom</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.money</groupId>
<artifactId>money-api</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.logging.Logger;

/**
* This class implements a {@link ExchangeRateProvider} that delegates calls to
Expand All @@ -48,6 +49,8 @@ public class CompoundRateProvider extends AbstractRateProvider {
*/
private final List<ExchangeRateProvider> providers = new ArrayList<>();

private static final Logger logger = Logger.getLogger(CompoundRateProvider.class.getName());

/**
* Constructor.
*
Expand Down Expand Up @@ -102,6 +105,10 @@ private void addProvider(ExchangeRateProvider prov) {
*/
@Override
public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) {
return getExchangeRate(conversionQuery, false);
}

public ExchangeRate getExchangeRate(ConversionQuery conversionQuery, boolean failFast) {
for (ExchangeRateProvider prov : this.providers) {
try {
if (prov.isAvailable(conversionQuery)) {
Expand All @@ -111,15 +118,18 @@ public ExchangeRate getExchangeRate(ConversionQuery conversionQuery) {
}
}
} catch (Exception e) {
throw new CurrencyConversionException(conversionQuery.getBaseCurrency(), conversionQuery.getCurrency(), null,
"Rate Provider did not return data though at check before data was flagged as available," +
" provider=" + prov.getContext().getProviderName() + ", query=" + conversionQuery, e);
if (failFast) {
throw new CurrencyConversionException(conversionQuery.getBaseCurrency(), conversionQuery.getCurrency(), null,
"Rate Provider did not return data though at check before data was flagged as available," +
" provider=" + prov.getContext().getProviderName() + ", query=" + conversionQuery, e);
} else {
logger.warning("Rate Provider did not return data though at check before data was flagged as available," +
" provider=" + prov.getContext().getProviderName() + ", query=" + conversionQuery + ", error=" + e.getMessage());
}
}
}
throw new CurrencyConversionException(conversionQuery.getBaseCurrency(), conversionQuery.getCurrency(), null,
"All delegate providers failed to deliver rate, providers=" + this.providers +
", query=" + conversionQuery);
}


}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.javamoney.moneta.spi;

import org.testng.annotations.Test;

import javax.money.convert.*;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;

import static org.testng.Assert.*;

public class CompoundRateProviderTest {

@Test
public void testGetExchangeRate() {
String baseCurrency = "EUR";
String termCurrency = "GBP";
LocalDate date = lastWeekTuesday();
ConversionQuery conversionQuery = ConversionQueryBuilder.of()
.setBaseCurrency(baseCurrency)
.setTermCurrency(termCurrency)
.set(date)
.build();

ExchangeRateProvider compoundRateProvider = MonetaryConversions.getExchangeRateProvider("ECB", "ECB-HIST90");
assertNotNull(compoundRateProvider.getExchangeRate(conversionQuery));
}

@Test
public void testGetExchangeRateAllProvidersFail() {
String baseCurrency = "EUR";
String termCurrency = "GBP";
LocalDate date = lastWeekTuesday();
ConversionQuery conversionQuery = ConversionQueryBuilder.of()
.setBaseCurrency(baseCurrency)
.setTermCurrency(termCurrency)
.set(date)
.build();

ExchangeRateProvider compoundRateProvider = MonetaryConversions.getExchangeRateProvider("ECB", "IMF");
assertThrows(CurrencyConversionException.class, () -> compoundRateProvider.getExchangeRate(conversionQuery));
}

@Test
public void testGetExchangeRateFailingFast() {
String baseCurrency = "EUR";
String termCurrency = "GBP";
LocalDate date = lastWeekTuesday();
ConversionQuery conversionQuery = ConversionQueryBuilder.of()
.setBaseCurrency(baseCurrency)
.setTermCurrency(termCurrency)
.set(date)
.build();

// Need to cast to CompoundRateProvider to access the getExchangeRate method that takes a boolean parameter
CompoundRateProvider compoundRateProvider = (CompoundRateProvider) MonetaryConversions.getExchangeRateProvider("ECB", "ECB-HIST90");
assertThrows(CurrencyConversionException.class, () -> compoundRateProvider.getExchangeRate(conversionQuery, true));
}

private LocalDate lastWeekTuesday() {
LocalDate today = LocalDate.now();
LocalDate lastTuesday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.TUESDAY));
return lastTuesday.minusWeeks(1);
}
}

0 comments on commit 69d0373

Please sign in to comment.