I am building an application to keep track of a stock portfolio. This has an Angular front-end with a REST services back-end implemented with Quarkus. The features of the first version: – manually add/remove stocks – retrieve latest prices from Yahoo Finance
This is the architecture of the application:
Project setup
Let us start with an empty project by specifying the extensions on https://code.quarkus.io and download the resulting zip. The necessary extension:
- RESTeasy JAX-R
- RESTeasy JSON-B
To make sure the development environment works, you start the development mode with Maven:
mvn compile quarkus:dev
In your browser, enter http://localhost:8080/hello and you will see “hello” as a response.
Add Yahoo finance API dependency
The retrieve the latest stock price, I add this dependency:
<dependency> <groupId>com.yahoofinance-api</groupId> <artifactId>YahooFinanceAPI</artifactId> <version>3.15.0</version> </dependency>
To get the stock information, including price:
Stock stock = YahooFinance.get(symbol);
Stock REST resource
It will be necessary get the latest stock price through a REST service, so we add the StockResource:
@Path("/{symbol}/latestPrice") @GET public Response stock(@PathParam("symbol") String symbol) throws IOException { Stock stock = YahooFinance.get(symbol); Response response = null; if (stock == null) { response = Response.status(Response.Status.NOT_FOUND).build(); } else { StockLatestPriceResponse stockResponse = new StockLatestPriceResponse(stock.getSymbol(), stock.getQuote().getPrice()); response = Response.ok(stockResponse).build(); } return response; }
We can test this by accessing this URL: http://localhost:8080/stocks/AAPL/latestPrice
Angular front-end
To bootstrap the Angular application, run this in the src/main directory:
ng new portfolio --skipGit --routing=true --style=scss
This creates a new directory “portfolio” with the Angular code. I rename that to “angular” to make it obvious that it contains Angular front-end code.
To run the front-end, change directory to the src/main/angular directory and run ng serve
. When you enter “http://localhost:4200” in your browser, you will see the example page with “portfolio app is running”.
I add the PrimeNG package – this contains nice user interface components.
npm install --save primeng npm install --save primeicons npm install --save @angular/cdk npm install --save chart.js npm install --save @fullcalendar/core
Portfolio page
Next I create a Portfolio page to display the list of stocks, and the service to retrieve the latest price.
ng generate component Portfolio ng generate service Stock
You can see how I implemented the page on my Github repository.
Stock price service
To retrieve the latest stock price, the StockService calls the REST endpoint implemented in Quarkus.
getStockLatestPrice(symbol: string): Observable<StockLatestPriceResponse> { return this.http.get<StockLatestPriceResponse>(`/stocks/${symbol}/latestPrice`); }
To check if it works, you can run ng serve
again.
You will see errors in the browser console:
GET http://localhost:4200/stocks/AAPL/latestPrice 404 (Not Found) GET http://localhost:4200/stocks/GOOG/latestPrice 404 (Not Found)
The Angular service expects that the Quarkus service is available at the same URL prefix, and this is http://localhost:4200. The Quarkus service actually lives at http://localhost:8080, so will will need a proxy.proxy.conf.json
{ "/stocks": { "target": "http://localhost:8080", "secure": false } }
If you have started Quarkus with mvn compile quarkus:dev
, then you can start the Angular app with ng serve --proxy-config proxy.conf.json
.
Combine Quarkus and Angular
So far, the Quarkus service and Angular application are separated. The Angular production build with ng build --prod
produces static files that can be served by Quarkus.
By default, ng build --prod
puts all produced files in the dist directory. We want those files in the src/main/resources/META-INF/resources directory. You can change that in the angular.json file:angular.json
"configurations": { "production": { "outputPath": "../resources/META-INF/resources",
After running ng build --prod
, you can start Quarkus with mvn compile quarkus:dev
and load the Angular app with http://localhost:8080/index.html
Running the application
Now we have an application that we can deploy and run. Quarkus gives you the ability to run the application as a native executable. When you build the application with mvn package -Pnative -Dquarkus.native.container-build=true -Dmaven.test.skip
, it will build a runner executable that contains everything it needs. This executable starts up very quickly and is great for running in a Docker container.
After building the executable, you can build a Docker image and run it:
docker build -f src/main/docker/Dockerfile.native -t quarkus/portfolio . docker run -i --rm -p 8080:80 quarkus/portfolio
After that, you can access the application at http://localhost:8080/index.html