Solr: własna implementacja ExchangeRateProvider dla CurrencyField

W poprzednim wpisie dotyczącym implementacji własnych funkcjonalności Solr pokazałem, jak zaimplementować własny filtr dla Solr. Dzisiaj zaimplementujemy własny mechanizm dostarczający kursów wymiany walut, czyli ExchangeRateProvider dla nowego typu pól – CurrencyField zaprezentowany w Solr 3.6.

Założenia

Aby pokazać, w jaki sposób zaimplementować własny provider dla typu CurrencyField zakładam, iż nasza aplikacja, która korzysta z Solr jest w stanie dostarczyć kursy w odpowiedniej formie. W tym celu zakładam, iż posiadamy bibliotekę, która udostępnia klasę implementującą następujący interfejs:

package pl.solr;

import java.util.List;

public interface UpToDateCurrencyProvider {
  Map<String, List<Currency>> getExchangeRates();
  void refresh();
  void initialize();
}

A klasa Currency wygląda następująco:

package pl.solr;

public class Currency {
  private String from;
  private String to;
  private double rate;

  public Currency(String from, String to, double rate) {
    this.from = from;
    this.to = to;
    this.rate = rate;
  }

  public String getFrom() {
    return from;
  }

  public String getTo() {
    return to;
  }

  public double getRate() {
    return rate;
  }
}

Podobnie, jak w poprzednim wpisie, pozwolę sobie pominąć szczegóły konfiguracji środowiska, budowania archiwum jar i tego typu szczegóły. Oprócz tego, założenie jest takie, aby nie komplikować kodu i skupić się na najważniejszym, czyli implementacji SolrPLCurrencyExchangeProvider.

Implementacja SolrPLExchangeRateProvider

package pl.solr;

import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.solr.common.ResourceLoader;
import org.apache.solr.common.SolrException;
import org.apache.solr.schema.ExchangeRateProvider;

public class SolrPLCurrencyExchangeProvider implements ExchangeRateProvider {
  private UpToDateCurrencyProvider provider;

  @Override
  public double getExchangeRate(String sourceCurrencyCode, String targetCurrencyCode) throws SolrException {
    if (sourceCurrencyCode == null || targetCurrencyCode == null) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot get exchange rate - source or target currency was null.");
    }
    List<Currency> exchangesRates = provider.getExchangeRates().get(sourceCurrencyCode);
    if (exchangesRates == null) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot get exchange rate - source currency exchange rates not found");
    }
    Currency exchange = null;
    for (Currency currency : exchangesRates) {
      if (currency.getTo().compareTo(targetCurrencyCode) == 0) {
        exchange = currency;
        break;
      }
    }
    if (exchange == null) {
      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot get exchange rate - target currency exchange rates not found");
    }
    return exchange.getRate();
  }

  @Override
  public void inform(ResourceLoader loader) throws SolrException {
    this.provider = new SolrPLUpToDateCurrencyProvider();
    this.provider.initialize();
    reload();
  }

  @Override
  public void init(Map<String, String> args) {
  }

  @Override
  public Set<String> listAvailableCurrencies() {
    return provider.getExchangeRates().keySet();
  }

  @Override
  public boolean reload() throws SolrException {
    provider.refresh();
    return true;
  }
}

Drobne wyjaśnienia dotyczące implementacji

Kilka słów wyjaśnienia, do implementacji pokazanej powyżej:

  • Linia 11 – tworzymy klasę implementującą interfejs ExchangeRateProvider z pakietu org.apache.solr.schema.
  • Linia 12 – mechanizm, który umożliwi nam pobieranie kursów wymiany.
  • Linia 15 – methoda getExchangeRate, czyli główna metoda naszego providera, w której pobieramy dane z naszego serwisu i zwracamy wartość double.
  • Linia 19 – pobranie dostępnych danych dotyczących wymiany. W produkcyjnym systemie należałoby te dane cache’ować. W tym przykładzie tego nie robimy, aby uprościć kod.
  • Linie 24 – 29 – pętla w której szukamy interesujących nas danych dotyczących kursu wymiany.
  • Linie 30 – 32 – jeżeli nie znaleźliśmy kursu wymiany, rzucamy wyjątek.
  • Linie 37 – 41 – tworzymy nasz serwis wymiany walut w metodzie inform oraz go inicjalizujemy.
  • Linie 48 – 50 – implementacja metody zwracającej dostępne kursy wymiany.
  • Linie 53 – 56 – implementacja metody odświeżającej kursy wymiany.

Konfiguracja

Po skompilowaniu i przygotowaniu biblioteki w formacie jar, kopiujemy ją do katalogu, gdzie Solr będzie ją widział. Możemy to uzyskać np. tworząc katalog lib w katalogu domowym Solr, a następnie dodać odpowiedni wpis do pliku solrconfig.xml, np. taki:

<lib dir="../lib/" regex="*.jar" />

Następnie zmieniamy plik schema.xml dodając typ oparty o solr.CurrencyField, na przykład w następujący sposób:

<fieldType class="solr.CurrencyField" name="currencyField" defaultCurrency="USD" providerClass="pl.solr.SolrPLExchangeRateProvider" />

Podsumowanie

Największym problemem podczas implementacji ExchangeRateProvider jest tak naprawdę dostarczenie interesujących nas danych, czyli informacji na temat kursów wymiany. Reszta, jak widać w powyższym przykładzie, nie jest mocno skomplikowana. Mam nadzieje, że tak jak poprzedni wpis, tak i ten, przyda się komuś kiedyś i oszczędzi mu kilku cennych godzin 🙂 Oczywiście powyższy przykład pobiera dane przy każdym odwołaniu, można to zoptymalizować dodając cache i odpowiedni czas ważności tych danych.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners. View more
Cookies settings
Accept
Privacy & Cookie policy
Privacy & Cookies policy
Cookie name Active
Save settings
Cookies settings