
This blog post demonstrates usage of Oracle Application Container Cloud and Database Cloud service. To be precise, it covers the following
- An introduction to Service bindings (in Application Container Cloud) including setup + configuration and leveraging them to integrate with Oracle Database Cloud service
- Developing a sample (Java SE based) application using JPA (Eclipselink implementation) for persistence and JAX-RS (Jersey framework) to expose a REST API
- Build, package and deploy the solution to the Application Container cloud using its REST APIs

The table below lists the components used
|
Component/service name
|
Description
|
|
|
|
|
Oracle Application Container Cloud
|
The aPaaS solution which hosts the Fat JAR based Java application exposing REST APIs
|
|
Oracle Database Cloud
|
hosts the application data
|
|
Oracle Storage Cloud
|
stores the application zip (for deployment)
|
|
Eclipselink
|
used as the JPA implementation (v 2.5.2)
|
|
Jersey
|
JAX-RS implementation (v 2.23.2)
|
|
Maven
|
Build tool. Makes use of the shade plugin to create a Fat JAR packaged with all dependent libraries
|
|
|
|
Service bindings: the concept
Service bindings serve as references to other Oracle Cloud services. At their core, they are a set of environment variables for a particular cloud service which are automatically seeded once you configure them. You can refer to these variables from within your application code. For example
String port = Optional.ofNullable(System.getenv("PORT")).orElse("8080"); //PORT is the environment variable
At the time of writing of this blog post, integration with following services are supported as far as service bindings are concerned - Oracle Database Cloud, Oracle Java Cloud and Oracle MySQL Cloud
What purpose do service bindings solve?
Service bindings make lives easier for developers
- It's possible to consume other Oracle Cloud services in a declarative fashion
- They allow secure storage of credentials required to access the service
- Connection details are conveniently stored as environment variables (de facto standard) and can be easily used within code. This in turn, shields you from hard coding connectivity information or using/building a custom mechanism to handle these concerns
How to configure them?
Service binding configuration can be configured in a couple of ways
- Metadata file (deployment.json) - It is possible to use this method both during as well as post application deployment
- Application Container Cloud console - this is possible only post application deployment i.e. the application specific menu exposes this feature

We will use option #1 in the sample presented in this blog and will be covered in depth later
About the sample
Pre-requisites
You need to have access to the below mentioned Oracle Cloud Platform services to execute this sample end to end. Please refer to the links to find out more with regards to procuring service instances
An Oracle Storage Cloud account is automatically provisioned along with your Application Container Cloud instance
Database Cloud service needs to be in the same identity domain as the Application Container Cloud for it to be available as a service binding
Architecture
The sample application presented in this blog is not complicated, yet, it makes sense to grasp the high level details with the help of a diagram

- As already mentioned, the application leverages JPA (DB persistence) and JAX-RS (RESTful) APIs
- The client invokes a HTTP(s) URL (GET request) which internally calls the JAX-RS resource, which in turn invokes the JPA (persistence) layer to communicate with Oracle Database Cloud instance
- Connectivity to the Oracle Database Cloud instance is achieved with the help of service bindings which expose database connectivity details as environment variables
- These variables are used within the code
Persistence (JPA) layer
Here is a summary of the JPA piece. Eclipselink is used as the JPA implementation and the sample makes use of specific JPA 2.1 features like automated schema creation and data seeding during application bootstrap phase
The table and its associated data will be created in Oracle Database cloud during application deployment phase. This approach been used on purpose in order to make this easy for you to test the application. It’s possible to manually bootstrap your Oracle Database Cloud instance with the table and some test data. You can turn off this feature by commenting out the highlighted line from persistence.xml

The important classes/components are as follows
|
Name
|
Description
|
|
|
|
|
persistence.xml
|
JPA deployment descriptor
|
|
PaasAppDev.java
|
JPA entity class
|
|
JPAFacade.java
|
Manages EntityManagerFactory life cycle and provides access to EntityManager
|
PaasAppDev.java
/**
* JPA entity
*
*/
@Entity
@Table(name = "PAAS_APPDEV_PRODUCTS")
@XmlRootElement
public class PaasAppDev implements Serializable {
@Id
private String name;
@Column(nullable = false)
private String webUrl;
public PaasAppDev() {
//for JPA
}
//getters & setters ommitted
}
JPAFacade.java
public class JPAFacade {
private static EntityManagerFactory emf;
private JPAFacade() {
}
public static void bootstrapEMF(String persistenceUnitName, Map\<String, String> props) {
if (emf == null) {
emf = Persistence.createEntityManagerFactory(persistenceUnitName, props);
emf.createEntityManager().close(); //a hack to initiate 'eager' deployment of persistence unit during deploy time as opposed to on-demand
}
}
public static EntityManager getEM() {
if (emf == null) {
throw new IllegalStateException("Please call bootstrapEMF(String persistenceUnitName, Map\<String, String> props) first");
}
return emf.createEntityManager();
}
public static void closeEMF() {
if (emf == null) {
throw new IllegalStateException("Please call bootstrapEMF(String persistenceUnitName, Map\<String, String> props) first");
}
emf.close();
}
}
Leveraging service binding information
It’s important to note how the service bindings are being used in this case. Generally, in case of standalone (with RESOURCE_LOCAL transactions) JPA usage, the DB connectivity information is stored as a part of the persistence.xml. In our sample, we are using programmatic configuration of EntityManagerFactory because the DB connection info can be extracted only at runtime using the following environment variables
- DBAAS_DEFAULT_CONNECT_DESCRIPTOR
- DBAAS_USER_NAME
- DBAAS_USER_PASSWORD
This is leveraged in Bootstrap.java (which serves as the entry point to the applicaiton)
/**
* The 'bootstrap' class. Sets up persistence and starts Grizzly HTTP server
*
*/
public class Bootstrap {
static void bootstrapREST() throws IOException {
String hostname = Optional.ofNullable(System.getenv("HOSTNAME")).orElse("localhost");
String port = Optional.ofNullable(System.getenv("PORT")).orElse("8080");
URI baseUri = UriBuilder.fromUri("[http://](http://)" + hostname + "/").port(Integer.parseInt(port)).build();
ResourceConfig config = new ResourceConfig(PaasAppDevProductsResource.class)
.register(MoxyJsonFeature.class);
HttpServer server = GrizzlyHttpServerFactory.createHttpServer(baseUri, config);
Logger.getLogger(Bootstrap.class.getName()).log(Level.INFO, "Application accessible at {0}", baseUri.toString());
//gracefully exit Grizzly and Eclipselink services when app is shut down
Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
Logger.getLogger(Bootstrap.class.getName()).info("Exiting......");
server.shutdownNow();
JPAFacade.closeEMF();
Logger.getLogger(Bootstrap.class.getName()).info("REST and Persistence services stopped");
}
}));
server.start();
}
private static final String PERSISTENCE\_UNIT\_NAME = "oracle-cloud-db-PU";
static void bootstrapJPA(String puName, Map\<String, String> props) {
JPAFacade.bootstrapEMF(puName, props);
Logger.getLogger(Bootstrap.class.getName()).info("EMF bootstrapped");
}
public static void main(String\[\] args) throws IOException {
Map\<String, String> props = new HashMap\<>();
props.put("javax.persistence.jdbc.url", "jdbc:oracle:thin:@" + System.getenv("DBAAS\_DEFAULT\_CONNECT\_DESCRIPTOR"));
props.put("javax.persistence.jdbc.user", System.getenv("DBAAS\_USER\_NAME"));
props.put("javax.persistence.jdbc.password", System.getenv("DBAAS\_USER\_PASSWORD"));
bootstrapREST();
bootstrapJPA(PERSISTENCE\_UNIT\_NAME, props);
}
}
REST (JAX-RS) layer
Jersey is used as the JAX-RS implementation. It has support for multiple containers - Grizzly being one of them and it’s used in this example as well. Also, the Moxy media provider is leveraged in order to ensure that JAXB annotated (JPA) entity class can be marshaled as both XML and JSON without any additional code
Important classes
|
Name
|
Description
|
|
|
|
|
PaasAppDevProductsResource.java
|
Contains logic to GET information about all (appdev/products) or a specific PaaS product (e.g. appdev/products/ACC)
|
PaasAppDevProductsResource.java
@Path("appdev/products")
public class PaasAppDevProductsResource {
@GET
@Path("{name}")
public Response paasOffering(@PathParam("name") String name) {
EntityManager em = null;
PaasAppDev product = null;
try {
em = JPAFacade.getEM();
product = em.find(PaasAppDev.class, name);
} catch (Exception e) {
throw e;
} finally {
if (em != null) {
em.close();
}
}
return Response.ok(product).build();
}
@GET
public Response all() {
EntityManager em = null;
List\<PaasAppDev> products = null;
try {
em = JPAFacade.getEM();
products = em.createQuery("SELECT c FROM PaasAppDev c").getResultList();
} catch (Exception e) {
throw e;
} finally {
if (em != null) {
em.close();
}
}
GenericEntity\<List\<PaasAppDev>> list = new GenericEntity\<List\<PaasAppDev>>(products) {
};
return Response.ok(list).build();
}
}
Build & cloud deployment
Now that you have a fair idea of the application, it’s time to look at the build, packaging & deployment
Seed Maven with ojdbc7 driver JAR
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc7 -Dversion=12.1.0.1 -Dpackaging=jar -Dfile=<download_path>\ojdbc7.jar -DgeneratePom=true
Here is a snippet from the pom.xml

Metadata files
The manifest.json
You can use the manifest.json file as it is
{
"runtime": {
"majorVersion": "8"
},
"command": "java -jar accs-dbcs-service-binding-sample-1.0.jar",
"release": {
"build": "27092016.1020",
"commit": "007",
"version": "0.0.2"
},
"notes": "notes related to release"
}
Service bindings in deployment.json
The deployment.json file should contain your service bindings and you would need to upload this file during deployment (explained below) for them to be associated with your Application Container cloud instance.
{
"services": \[
{
"identifier": "DBService",
"type": "DBAAS",
"name": \<Oracle DB Cloud service name>,
"username": \<Oracle DB Cloud username>,
"password": \<Oracle DB Cloud password>
}\]
}
You need to replace the placeholders with the appropriate values. Here is an example
{
"services": \[
{
"identifier": "OraDBService",
"type": "DBAAS",
"name": OracleCloudTestDB,
"username": db\_user,
"password": Foo@Bar\_007
}\]
}
In case of multiple service bindings for the same service (e.g. Java Cloud), the Application Container Cloud service automatically generates a unique set of environment variables for each service instance
Please refer to the following documentation if you need further details
Build & zip
Build JAR and zip it with (only) the manifest.json file to create a cloud-ready artifact
cd <code_dir>
mvn clean install
zip accs-dbcs-service-binding-sample.zip manifest.json target\accs-dbcs-service-binding-sample-1.0.jar
Upload application zip to Oracle Storage cloud
You would first need to upload your application ZIP file to Oracle Storage Cloud and then reference it later. Here are the steps along with the cURL commands
Please refer to the following documentation for more details
Get authentication token for Oracle Storage cloud
you will receive the token in the HTTP Response header and you can use it to execute subsequent operations
curl -X GET -H "X-Storage-User: Storage-<identity_domain>:<user_name>" -H "X-Storage-Pass: <user_password>" "storage_cloud_URL" //template
curl -X GET -H "X-Storage-User: Storage-domain007:john.doe" -H "X-Storage-Pass: foo@bar" "https://domain007.storage.oraclecloud.com/auth/v1.0" //example
Create a container in Oracle Storage cloud (if it doesn't already exist)
curl -X PUT -H "X-Auth-Token: <your_auth_token>" "<storage_cloud_container_URL>" //template
curl -X PUT -H "X-Auth-Token: AUTH_foobaar007" "https://domain007.storage.oraclecloud.com/v1/Storage-domain007/accscontainer/" //example
Upload your zip file into the container (zip file is nothing but a Storage Cloud object)
curl -X PUT -H "X-Auth-Token: <your_auth_token>" -T <zip_file> "<storage_cloud_object_URL>" //template
curl -X PUT -H "X-Auth-Token: AUTH_foobaar007" -T accs-dbcs-service-binding-sample.zip "https://domain007.storage.oraclecloud.com/v1/Storage-domain007/accscontainer/accs-dbcs-service-binding-sample.zip" //example
Things to note
- the <zip_file> is the application zip file which needs to uploaded and should be present on your file system from where you're executing these commands
- the (storage cloud) object name needs to end with .zip extension (in this context/case)
Deploy to Application Container Cloud
Once you have finished uploading the ZIP, you can now reference its (Oracle Storage cloud) path while using the Application Container Cloud REST API which you would use in order to deploy the application. Here is a sample cURL command which makes use of the REST API
curl -X POST -u joe@example.com:password \
-H "X-ID-TENANT-NAME:domain007" \
-H "Content-Type: multipart/form-data" -F "name=accs-dbcs-service-binding-sample" \
-F "runtime=java" -F "subscription=Monthly" \
-F "deployment=@deployment.json" \
-F "archiveURL=accscontainer/accs-dbcs-service-binding-sample.zip" \
-F "notes=notes for deployment" \
https://apaas.oraclecloud.com/paas/service/apaas/api/v1.1/apps/domain007
During this process, you will also be pushing the deployment.json metadata file which contains the service bindings info (should be present on the file system on which the command is being executed). This in turn will automatically seed the required environment variables during application creation phase
More details available here
Test the application
Once deployment is successful, you should be able to see the deployed application and its details in Application Container cloud

Access your Oracle Database Cloud service
You can use Oracle SQL developer or similar client to confirm that the required table has been created and seeded with some test data
Details on how to configure your Oracle Database Cloud instance to connect via external tool (like SQL Developer) is out of scope of this article, but you can follow the steps outlined in the official documentation to set things up quickly

Access the REST endpoints
|
Purpose
|
Command
|
|
|
|
|
GET all products
|
curl -H "Accept: application/json" https://<application_URL>/appdev/products
|
|
GET a specific product
|
curl -H "Accept: application/json" https://<application_URL>/appdev/products/<product_name>
e.g. curl -H "Accept: application/json" https://<application_URL>/appdev/products/ACC
Refer above image for all product names
|
| | |
Please use the below mentioned application URL formats
https://accs-dbcs-service-binding-sample-<identity_domain>.apaas.<region>.oraclecloud.com/ //template
https://accs-dbcs-service-binding-sample-domain007.apaas.us2.oraclecloud.com/ //example
**The views expressed in this post are my own and do not necessarily reflect the views of Oracle.