- Java EE 8 High Performance
- Romain Manni Bucau
- 590字
- 2021-06-30 19:14:24
Provision some data
At this point, we have our application. Now, we need to ensure that it has some data and, then, move on to evaluating its performance.
Without delving too much into the business details, we will implement the provisioning in two passes:
- Find all the symbols to update
- For each symbol found, update the price in the database
To do so, we will use two public webservices:
- http://www.cboe.com/publish/ScheduledTask/MktData/cboesymboldir2.csv, to find a set of symbols
- https://query1.finance.yahoo.com/v10/finance/quoteSummary/{symbol}?modules=financialData, to find the current price of each quote
The first one is a plain CSV file, which we will parse without any library to keep things simple and because the format does not require special escaping/parsing. The second one will return a JSON payload, which we can read directly using the JAX-RS 2.1 client API.
Here is how we can retrieve our data:
private String[] getSymbols(final Client client) {
try (final BufferedReader stream = new BufferedReader(
new InputStreamReader(
client.target(symbolIndex)
.request(APPLICATION_OCTET_STREAM_TYPE)
.get(InputStream.class),
StandardCharsets.UTF_8))) {
return stream.lines().skip(2/*comment+header*/)
.map(line -> line.split(","))
.filter(columns -> columns.length > 2 && !columns[1].isEmpty())
.map(columns -> columns[1])
.toArray(String[]::new);
} catch (final IOException e) {
throw new IllegalArgumentException("Can't connect to find symbols", e);
}
}
Note that we directly read a buffered reader backed by the HTTP response stream. Once the symbols are extracted, we can simply iterate over them and request the price of each quote:
try {
final Data data = client.target(financialData)
.resolveTemplate("symbol", symbol)
.request(APPLICATION_JSON_TYPE)
.get(Data.class);
if (!data.hasPrice()) {
LOGGER.warning("Can't retrieve '" + symbol + "'");
return;
}
final double value = data.getQuoteSummary().getResult().get(0)
.getFinancialData().getCurrentPrice().getRaw();
final Quote quote = quoteService.mutate(symbol, quoteOrEmpty ->
quoteOrEmpty.map(q -> {
q.setValue(value);
return q;
}).orElseGet(() -> {
final Quote newQuote = new Quote();
newQuote.setName(symbol);
newQuote.setValue(value);
quoteService.create(newQuote);
return newQuote;
}));
LOGGER.info("Updated quote '" + quote.getName() + "'");
} catch (final WebApplicationException error) {
LOGGER.info("Error getting '" + symbol + "': " + error.getMessage()
+ " (HTTP " + (error.getResponse() == null ? "-" :
error.getResponse().getStatus()) + ")");
}
This piece of code sends an HTTP request, thanks to the JAX-RS client API and JSON-B, which unmarshalls a data model. Then, we use the obtained data to update our database quote if it already exists; otherwise, we use the data to create the database quote.
The code now needs to be wired to be executed. We have multiple options here:
- Execute it at startup
- Execute it regularly
- Execute it when an endpoint is called
In the context of this book, we will use the first two options. The startup is common for us, even if it is not as realistic, because once started, we will get some data. The second option will use an EJB 3.2 @Schedule, which will run hourly.
The startup implementation requires a simple CDI bean with a method calling the previous logic when @ApplicationScoped is created (at startup):
@ApplicationScoped
public class InitialProvisioning {
@Inject
private ProvisioningService provisioningService;
public void onStart(@Observes @Initialized(ApplicationScoped.class) final ServletContext context) {
provisioningService.refresh();
}
}
The scheduling is done, thanks to the Enterprise Java Bean @Schedule API, which allows us, in one annotation, to request the container to regularly execute a method:
@Singleton
@Lock(WRITE)
public class DataRefresher {
@Inject
private ProvisioningService provisioningService;
@Schedule(hour = "*", persistent = false, info = "refresh-quotes")
public void refresh() {
provisioningService.refresh();
}
}
- Mastering ElasticSearch
- PLC控制程序精編108例
- Windows Server 2012 Hyper-V:Deploying the Hyper-V Enterprise Server Virtualization Platform
- Google系統架構解密:構建安全可靠的系統
- Linux網絡內核分析與開發
- 奔跑吧 Linux內核(入門篇)
- 移動應用UI設計模式(第2版)
- Microsoft Operations Management Suite Cookbook
- Mobile First Design with HTML5 and CSS3
- 計算機系統的自主設計
- Mastering Windows 8 C++ App Development
- Linux從入門到精通(視頻教學版)
- 15分鐘!畫出我的漫畫角色:賣萌篇
- SQL Server on Azure Virtual Machines
- 從零開始學Windows 7