This is a two-part blog series which covers setup, development, integration and deployment aspects of developing lightweight Java EE applications for the Oracle Application Container Cloud service – all with the help of a sample application. The following are the key items which will be covered in this post

 

  • Developing ‘right sized’ applications by using ’just enough’ of the Java EE platform, thanks to Wildfly Swarm
  • Leveraging a scalable and easy to use cloud platform: Oracle Application Container Cloud service
  • Evolutionary not revolutionary: use your existing Java EE skills and continue building WARs
  • Second part of this blog will focus more on Oracle Developer Cloud service

 

 

 

 

 

 

 

Introduction

Here is a quick peek into the major services/tools/frameworks which we’ll be used for the sample application

 

Runtime/Service/Framework/Tool

Version

 

 

Oracle JDK

7

Java EE Platform

Java EE 7

Oracle Application Container Cloud Service

16.3.3

Wildfly Swarm

1.0.0

Maven

3.3.9

Netbeans IDE

8.1

 

Oracle Cloud services

 

Oracle Application Container Cloud

 

Oracle Application Container Cloud service provides a robust, polyglot PaaS infrastructure for building lightweight applications in Oracle Cloud. Without going into the details, here are the major highlights of this service

 

  • Open & Polyglot: you're free to leverage any of the thousands of open source or commercial Java SE, Node or PHP (latest addition) frameworks. More programming languages will be added in future
  • Docker based: Built on the proven containerization technology
  • Elastic: Your applications can be easily scaled in or out using the REST API or the service console
  • Easy to manage: update your language runtimes to their latest releases with a single click
  • Profiling: Java based applications can leverage the Flight Recorder to monitor the JVM and analyze using Mission Control
  • Provides integration with other Oracle Cloud services: Developer Cloud, Java Cloud, Database Cloud

 

Oracle Developer Cloud

 

Oracle Developer Cloud Service is a cloud-based software development Platform as a Service (PaaS) and a hosted environment for your application development infrastructure. It provides an open source standards-based solution to develop, collaborate, build, and deploy applications within Oracle Cloud.

 

Platform, frameworks & tools

 

Wildfly Swarm

 

WildFly Swarm is an open source framework that allows the selective reconstitution of Java EE APIs (JAX-RS, CDI, EJB JPA, JTA etc.) within your applications. The goal is to use just enough of a Java EE application server to support whatever subset of the APIs your application requires.

 

Maven

 

Apache Maven is a software project management and comprehension tool. Based on the concept of a project object model (POM), Maven can manage a project's build, reporting and documentation from a central piece of information.

 

IDE

 

For development, this sample uses NetBeans which is a free, open source and immensely popular IDE. For more details, please feel free to check https://netbeans.org/features/index.html

 

Why NetBeans ?

 

  • Integration with Oracle Developer Cloud service powered by the Team Server plug-in
  • Great for Java EE development with support for the latest (v7) platform version
  • Excellent Maven support

 

Diving in…

 

Introducing the Ticker Tracker application

 

Here is a quick intro to the functional aspect of the application. Ticker Tracker revolves around the ability to keep track of stock prices of NYSE scrips.

 

  • Users can check the stock price of a scrip (listed on NASDAQ) using a simple REST interface
  • Real time price tracking is also available – but this is only for Oracle (ORCL)

 

The logic itself is kept simple in order to focus on the core concepts rather than get sucked into complexity of technical implementation. The sample application uses below mentioned Java EE APIs

 

API

Version

JSR #

 

 

 

JAX-RS

2.0

JSR-339

WebSocket

1.0

JSR-356

EJB

3.2

JSR-345

CDI

1.1

JSR-346

JSON-P

1.0

JSR-353

 

Evolutionary not revolutionary

Wildfly Swarm supports two development modes

 

Uber JAR (Java SE)

 

  • Include the required components/fractions (e.g. JAX-RS, CDI, JPA etc.) in pom.xml
  • Write your code
  • Configure your components and deployment using the Swarm Container API within a main method and

 

Hybrid Mode i.e. WAR to JAR (Java EE roots)

 

  • Stick to the business logic which you have already developed
  • Let Swarm auto-magically detect and configure required fractions and create an Uber JAR from your WAR

 

Why go with WAR?

 

  • Less intrusive: let’s you continue your development process with minimum changes/additions
  • Suitable for existing applications: In addition to embarking upon developing Uber JAR Java EE application from scratch, one would also want to retrofit existing deployments to the Fat/Uber JAR model
  • Developer friendly: As a developer, you would do not need to wrap your head around auxiliary concerns such as WAR to Uber JAR conversion – just continue writing your Java EE application and let the framework help you out with this
  • As mentioned before, the Swarm Maven plugin does the job of creating your Fat/Uber JAR
  • Use the Swarm Maven plugin to assist you with the Uber JAR creation

 

Implementation details

 

Let’s go over this in a step-by-step manner

 

Initialize NetBeans project

Start with a Maven based Java EE project in NetBeans. If you want to explore this in further detail, feel free to refer NetBeans documentation around this topic (starting with this source)

 

 

 

 

 

It’s not necessary to include/link a Java EE application server at this point. You can opt for ‘No Server selected’ and click Finish to complete the process

 

 

After bootstrapping the Maven based Java EE Web application project, you should see the following project structure along with a pom.xml

 

 

 

Note: the only dependency defined in your pom.xml would be the Java EE 7 APIs

 

..........
<dependencies>
        <dependency>
            <groupId>javax</groupId>
            <artifactId>javaee-web-api</artifactId>
            <version>7.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
..........

 

Add Swarm specific magic

 

Once NetBeans sets up the base version of your project, all you need to do is include the wildfly-swarm-plugin configuration your Maven pom.xml

 

......
<plugin>
                <groupId>org.wildfly.swarm</groupId>
                <artifactId>wildfly-swarm-plugin</artifactId>
                <version>1.0.0.Final</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>package</goal>
                        </goals>
                    </execution>
                </executions>
</plugin>
......

 

Note: You can choose to explicitly add dependencies for the fractions (the required Java EE components) which you are using in your application or you can offload this duty to Swarm which in turn will automatically detect the required fractions (after code introspection) and pull them during the build phase. Below is an example of how you can add a JAX-RS fraction for RESTful services

 

.....
<dependency>  
    <groupId>org.wildfly.swarm</groupId>  
    <artifactId>jaxrs</artifactId>  
</dependency>
.....

 

Once the setup process is complete, we can proceed with our application development.

 

Develop business logic

Let’s look a quick look at the classes/code artifacts along with some code snippets to get you warmed up.

 

 

RealTimeStockTicker.java

 

  • A server side WebSocket endpoint (@ServerEndpoint) to broadcast stock prices to connected clients/users
  • The data is pushed to clients in an asynchronous manner, thanks to this feature in the Java WebSocket API
  • Please note that for this sample, users are restricted to be able to track real time prices for Oracle (ORCL) stocks only

 

.....
public void broadcast(@Observes @StockDataEventQualifier String tickTock) {

        for (final Session s : CLIENTS) {
            if (s != null && s.isOpen()) {
                /**
                 * Asynchronous push
                 */
                s.getAsyncRemote().sendText(tickTock, new SendHandler() {
                    @Override
                    public void onResult(SendResult result) {
                        if (result.isOK()) {
                            Logger.getLogger(RealTimeStockTicker.class.getName()).log(Level.INFO, "Price sent to client {0}", s.getId());
                        } else {
                            Logger.getLogger(RealTimeStockTicker.class.getName()).log(Level.SEVERE, "Could not send price update to client " + s.getId(),
                                    result.getException());
                        }
                    }
                });
            }


        }
}
.....

 

StockPriceScheduler.java

 

    • A Singleton EJB (@Singleton) acts as the source of stock price data
    • It uses native (EJB) scheduling (combination of TimerService and @Timeout) capabilities to periodically poll the Google Finance REST endpoint using the JAX-RS client API to pull stock prices
    • Leverages CDI capabilities like events and qualifiers (@Qualifier) to push latest stock prices to the connected WebSocket clients in real time

 

.....
@Timeout
public void timeout(Timer timer) {

        /**
         * Invoked asynchronously
         */
        Future<String> tickFuture = ClientBuilder.newClient().
                target("https://www.google.com/finance/info?q=NASDAQ:ORCL").
                request().buildGet().submit(String.class);

        /**
         * Extracting result immediately with a timeout (3 seconds) limit. This
         * is a workaround since we cannot impose timeouts for synchronous
         * invocations
         */
        String tick = null;
        try {
            tick = tickFuture.get(3, TimeUnit.SECONDS);
        } catch (InterruptedException | ExecutionException | TimeoutException ex) {
            Logger.getLogger(StockPriceScheduler.class.getName()).log(Level.INFO, "GET timed out. Next iteration due on - {0}", timer.getNextTimeout());
            return;
        }

        if (tick != null) {
            /**
             * cleaning the JSON payload
             */
            tick = tick.replace("// [", "");
            tick = tick.replace("]", "");
            msgEvent.fire(StockDataParser.parse(tick));
        }
}
.....

 

StockPriceResource.java

A simple REST endpoint (@Path, @GET) exposed for the end users to be able to query (on demand) the stock price of any index listed on NYSE

 

.....
@GET
public String getQuote(@QueryParam("ticker") final String ticker) {


        Response response = ClientBuilder.newClient().
                target("https://www.google.com/finance/info?q=NASDAQ:" + ticker).
                request().get();


        if (response.getStatus() != 200) {
            //throw new WebApplicationException(Response.Status.NOT_FOUND);
            return String.format("Could not find price for ticker %s", ticker);
        }
        String tick = response.readEntity(String.class);
        tick = tick.replace("// [", "");
        tick = tick.replace("]", "");


        return StockDataParser.parse(tick);
}
.....

 

RESTConfig.java

Basic configuration class for the JAX-RS container

 

StockDataParser.java

A simple utility class which leverages the JSON Processing (JSON-P) API to filter the JSON payload obtained from the Google Finance REST endpoint and returns data useful for the end users

 

beans.xml

This is the CDI configuration file. Although it does not have too much content, it does enable the CDI events feature

 

Execution

 

In this section, we’ll see how to

  • Build and run the example on your local machine
  • Package it as per Oracle Application Container semantics, upload it and see our sample app in action in the cloud

 

Standalone mode

Now that we have our business logic ready, it’s time to build our application! You can do so by right-clicking on your project in NetBeans and choosing Build with dependencies (please note that this might take time during the first iteration)

 

 

The file structure of your maven build directory (target) will look similar to this. Please note that the ticker-tracker-swarm.jar is the Uber JAR produced by Wildfly Swarm plugin

 

 

Since the artifact produced by the build process is just a JAR file, running this is very simple (all you need is a JRE). Here is template for the deployment command

 

java -jar -Dswarm.http.port=<port_number> -Dswarm.context.path=/<custom_context_root> <full_path_to_jarfile>

 

Here is an example

 

java -jar -Dswarm.http.port=9090 -Dswarm.context.path=/ticker-tracker /work/demo/ticker-tracker-swarm.jar

 

Your application should now be up and running on port 9090 with the ticker-tracker  context root

 

  • Access the REST endpoint as follows - http://localhost:9090/ticker-tracker/api/stocks?ticker=AAPL
  • Here is the WebSocket endpoint - ws://localhost:9090/ticker-tracker/rt/stocks

 

Configuration

The below mentioned parameters are specific to Wildfly Swarm and can be used to configure its containers and components

 

Parameter

Description

swarm.http.port

The port on which the Servlet container (Undertow in case of Wildfly) accepts incoming connections. This is 8080 by default

swarm.context.path

Defines a custom context root for your web application

 

Package, upload to Application Container Cloud

 

Package

 

Here are the important points to note in terms of packaging as far as the sample application in this post is concerned (some of these are generally applicable to all JAR based deployments on Application Container Cloud). For a deep dive into this topic, please refer the Packaging Your Application section in the product documentation

 

  • Its packaged as an Uber (Fat) JAR
  • Uses a manifest.json (compulsory deployment artifact) which includes the launch command as well

 

{
    "runtime": {
        "majorVersion": "8"
    },
    "command": "java -jar -Dswarm.https.port=$PORT -Dswarm.context.path=/ticker-tracker ticker-tracker-swarm.jar",
    "release": {
        "build": "24082016.2052",
        "commit": "007",
        "version": "0.0.1"
    },
    "notes": "notes related to release"
}

 

 

A note about the $PORT environment variable

As a platform, Application Container Cloud is ephemeral by nature and parameters like hostname and port etc. are allocated dynamically by the platform and are subject to change (in case your application is redeployed). The startup command takes this into account and binds to the dynamic port allotted by the underlying Application Container Cloud instance. More on this in the following sections - Making the Application Configurable at Runtime, Design Considerations

 

Upload

Oracle Application Container Cloud provides multiple channels for uploading our application

 

Using the Web UI

  • You can choose to upload your ZIP file directly, or
  • You can upload it to your Storage Cloud Service instance first and provide its path

 

Using REST API – Refer Create an Application for the API semantics

 

You can refer the Getting Started with Oracle Application Container Cloud Service tutorial to get a better understanding of the above mentioned points with a focus on the following topics

 

Test out your Cloud deployment

 

To check price of a specific stock just issue a GET request on the specified URL. Mentioned below is the template

 

https://<your-accs-app-url>/ticker-tracker/api/stocks?ticker=<ticker_symbol>

 

Example:

 

https://ticker-tracker-mydomain.apaas.em1.oraclecloud.com/ticker-tracker/api/stocks?ticker=AAPL

 

For real time tracking of Oracle stock prices, you would need a WebSocket client. I would personally recommend using the client which can be installed into Chrome browser as a plugin – Simple WebSocket Client. This client will be used to demonstrate the real time stock tracking feature. The following is a template for the URL of the WebSocket endpoint

 

wss://<your-accs-app-url>/ticker-tracker/rt/stocks

 

Use this as the value for the URL attribute in the client and click on the Open button to start tracking

 

Example

 

wss://ticker-tracker-mydomain.apaas.em1.oraclecloud.com/ticker-tracker/rt/stocks

 

Note: Please notice the fact that we're using secured channel for both REST (https) and WebSocket (wss) protocols since the applications deployed on Application Container Cloud service only listen on secured ports (via a load balancer which the end users and developers do not need to worry about)

 

 

 

 

You should start receiving real time price updates in the Message Log box. You can choose to disconnect any time by clicking the Close button. You now have a lightweight Java EE application running and fully functional on the Oracle Application Container Cloud !

 

This marks the end of part I. As promised, the second part of this post will focus on Oracle Developer Cloud service features such as IDE Integration for source code management, project configuration, build monitoring, seamless deployment to Application Container and more…

 

 

 

**The views expressed in this post are my own and do not necessarily reflect the views of Oracle.