tag:blogger.com,1999:blog-17662033929123362492024-03-13T01:14:02.072+01:00VENNSTER BLOGVennster is the company behind Parta. Parta helps governments, companies, cooperations and other groups to create solutions and make decisions together. In a completely transparant and safe way.
Our guiding principles include:
- Being open. Transparency increases trust in the decision. To accomplish that, results should be irrefutable and participation should be available to everyone, anytime, and anywhere.
- Privacy. All design decision are made with privacy of our customers and users in mind.Ronald van Luttikhuizenhttp://www.blogger.com/profile/16349079496824277926noreply@blogger.comBlogger131125tag:blogger.com,1999:blog-1766203392912336249.post-22447362504289803572020-10-19T19:31:00.007+02:002020-10-19T19:35:03.938+02:00Updating SSL certificates in Kubernetes on Oracle Cloud<p>When you secure your servers and APIs, you need SSL certificates. Since they don't last for ever, you will have to update them every year, or every other year.</p><p>In OKE (Kubernetes on Oracle Cloud), there are two slightly different ways of doing this, depending on the kind of component you are using. Unfortunately, the Oracle documentation does not describe how to update SSL certificates in Kubernetes. </p><h4 style="text-align: left;">Update an Ingress controller </h4><div>An ingress that is used for SSL termination looks something like this: </div><div><br /></div><div><ol class="ol" style="background-color: white; color: #666666; font-family: "Oracle Sans", -apple-system, system-ui, "Segoe UI", "Helvetica Neue", sans-serif; font-size: 17.6px; margin: 0px 0px 20px; padding-left: 30px;"><div class="uk-position-relative" style="outline: 0px; position: relative;"><pre class="pre codeblock scrollcopy vl-pre-with-toolbar" style="background-attachment: initial; background-clip: initial; background-image: initial; background-origin: initial; background-position: initial; background-repeat: initial; background-size: initial; border-bottom-color: rgb(196, 206, 215); border-bottom-style: solid; border-image: initial; border-left-color: rgb(196, 206, 215); border-left-style: solid; border-radius: 0px 0px 3px 3px; border-right-color: rgb(196, 206, 215); border-right-style: solid; border-top-color: initial; border-top-style: initial; border-width: 0px 1px 1px; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 0.875rem; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.5; margin-bottom: 20px; margin-top: 0px; overflow: auto; padding: 10px; tab-size: 4;"><code style="font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;">apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: my-ing
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
tls:
- secretName: my-ssl-secret-name
rules:
- http:
paths:
- backend:
serviceName: my-backend-svc
servicePort: 8088</code></pre></div></ol></div><div>The Oracle documentation has a <a href="https://docs.cloud.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengsettingupingresscontroller.htm" rel="nofollow" target="_blank">clear description of how to setup an ingress controller with TLS.</a> Basically you create an ingress controller and a TLS secret and apply an ingress.yaml. Note that when you check the load balancer in the OCI console that is associated with the ingress, there is no SSL certificate listed there, this is completely handled from within the Kubernetes cluster.</div><div><br /></div><div>There is no mention of how to update the certificate but that is actually very simple: you can update the values in the existing Kubernetes secret (for example using the dashboard or a script) and the ingress controller will pick up the new certificate automatically. </div><div><br /></div><h4 style="text-align: left;">Update a service of type Load Balancer</h4><div>A service of type load balancer yaml looks something like this: </div><div><br /></div><div><pre class="pre codeblock scrollcopy vl-pre-with-toolbar" style="background: rgb(255, 255, 255); border-bottom-color: rgb(196, 206, 215); border-bottom-style: solid; border-image: initial; border-left-color: rgb(196, 206, 215); border-left-style: solid; border-radius: 0px 0px 3px 3px; border-right-color: rgb(196, 206, 215); border-right-style: solid; border-top-color: initial; border-top-style: initial; border-width: 0px 1px 1px; color: #666666; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 0.875rem; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.5; margin-bottom: 20px; margin-top: 0px; overflow: auto; padding: 10px; tab-size: 4;"><code style="font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace;">kind: Service
apiVersion: v1
metadata:
name: my-frontend-service
annotations:
service.beta.kubernetes.io/oci-load-balancer-ssl-ports: "443"
service.beta.kubernetes.io/oci-load-balancer-tls-secret: my-ssl-secret-name<br />
spec:
selector:</code></pre></div><div>Again, the Oracle documentation has <a href="https://docs.cloud.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengcreatingloadbalancer.htm" rel="nofollow" target="_blank">a clear description of how to setup a service with a load balancer. </a> It describes a similar procedure: you create a service and secret in Kubernetes and apply this. However, because the kind of deployment is a service which specifies a load balancer, the certificate is picked up by the OCI Load Balancer <b><i><u>and copied there.</u></i></b></div><div><br /></div><div>Again there is no mention of how to update the certificate. When you change the value of the certificate in the secret in Kubernetes, the change is not picked up by the OCI Load Balancer. There are a lot of warnings in the documentation not to change it in OCI directly, so that is not an option. The procedure to update the certificate is:</div><div><ol style="text-align: left;"><li>Create <u><i><b>a new secret</b></i></u> with a new certificate and private key</li><li>Update the service yaml to point to the new secret</li><li>Apply the updated service yaml (don't create the service, just apply the updated yaml on the existing service) using <span style="font-family: courier;">kubectl apply -f [name of your yaml]</span></li><li>Delete the previous secret.</li></ol></div><div>To streamline the procedure, we have decided to create a new secret for both the ingress controller and the service so we don't end up with multiple secrets containing the same wildcard certificate and to make sure we can use one procedure for both types of components.</div><p>I hope the documentation will be updated by Oracle to include an instruction for updating SSL certificates. In the mean time I hope this post helps you when you need to update your SSL certificates. </p><p>Happy coding! 😀</p>Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-35986470027523564532020-04-22T11:05:00.003+02:002020-04-22T11:16:51.971+02:00Migrating from Developer Cloud Service classic to Developer Cloud in OCI<div dir="ltr" style="text-align: left;" trbidi="on">
<span style="font-family: inherit;">One of our customers was still running a Developer Cloud Classic instance. We decided to migrate to Developer Cloud. Since the inception of Oracle Cloud and Oracle Platform as a service, services have moved from "Classic" to "Autonomous" to "Native". What does this mean and why does Oracle have all these different types of services in their cloud? And why would you care? Let's go back in time a little bit.</span><br />
<span style="font-family: inherit;"><br /></span>
<br />
<h2 style="text-align: left;">
A history lesson</h2>
Oracle started with a Cloud Infrastructure and Platform (PaaS) and Software services (SaaS) to catch up with competitors like Amazon (AWS) and Microsoft (Azure). Soon after realizing the first generation infrastructure an improvement project was started. This resulted in the current Oracle Cloud Infrastructure (OCI) with compartments, services that can be used by different PaaS services, improved networking etc. At the same time, the first generation of PaaS services was improved, to become "Autonomous": the customer does not have to worry about maintaining the platform, this is done by Oracle. This resulted in products like Oracle Autonomous Data Warehouse and Autonomous Oracle Integration Cloud. The name "Autonomous" was quickly dropped from most services except Database related products, but the advantage was clear: Oracle manages the platform instances, so customers don't have to worry or worry less about availability, upgrades and patches. A number of these services were not using the new features of the Oracle Cloud Infrastructure. Oracle released new platform services: so called "native" services that use the networking, compartment, notification and other features of OCI. Note that Autonomous Database products and services like Kubernetes Engine and Function were native from the start.<br />
<br />
Still confused? Let's look at an example: Oracle Integration Cloud.<br />
<br />
<h3 style="text-align: left;">
Example: OIC</h3>
Integration (also known as Oracle Integration Cloud or OIC) started with Integration Classic. When you provisioned OIC Classic it was provisioned in the Oracle's first generation, or classic, infrastructure. The next generation, which was called Autonomous OIC for a while, is/was running in Oracle Cloud Infrastructure. However, it is not making use of all the native services or functionality that OCI offers: you can't define the compartment it is provisioned in, it does not use the notification services, it does not have Terraform support etc. It is running in the specifically dedicated <i>ManagedCompartmentForPaaS</i> compartment, that gets automatically created when you provision (non-native) Oracle Integration The latest (and hopefully last) installment is Oracle Integration, which is native. When you provision it, you must create a compartment for it first and it uses all the available services (networking, notification etc.) of Oracle Cloud Infrastructure.<br />
<br />
It has several advantages to move to Oracle Cloud Infrastructure native services:<br />
<br />
<ul style="text-align: left;">
<li>Organize cloud resources into a hierarchy of logical compartments.</li>
<li>Create fine-grained access policies for each compartment.</li>
<li>Support for Terraform for provisioning</li>
<li>Usage of Security and network features in Oracle Cloud Infrastructure</li>
<li>Last but not least, new features are being added to the native service, not to the non-native services.</li>
</ul>
<br />
<h2 style="text-align: left;">
Migration of Oracle Developer Cloud Classic</h2>
<div>
<br /></div>
Now that we know how Oracle moves her services, what is the situation for Oracle Developer? Oracle Developer Cloud Classic is provisioned in the classic infrastructure and as a result, uses Oracle Classic infrastructure components for load balancing, networking, storage, etc. There is no native Developer Cloud service (yet?). However, you can move your Developer Cloud Service Classic to OCI (in the dedicated <i>ManagedCompartmentForPaaS</i> compartment). Developer Cloud service offers different features: a GIT repository, build jobs, deployment jobs, wiki, issue system, to name a few. For a number of these features you need resources. From Developer Cloud Classic you can connect to OCI to use the resources. For example: a build job needs a build VM and storage to store the artifacts. So even though the Developer Cloud Service itself is not running in a compartment of your choice, the jobs you are running and the code you are storing is making use of these features. But Developer Cloud Service itself, also uses networking to give you as a developer access to the console. Think about the load balancer, an IP address etc. For this customer, we wanted to remove all resources from the Classic Infrastructure, we already migrated Mobile Cloud Service to Mobile Hub and API Platform Classic to API Platform. Developer Cloud Classic was the last man standing...<br />
<br />
If you are not interested in my experience of the migration, but just want to go ahead and do it, you can find the Oracle documentation <a href="https://docs.oracle.com/en/cloud/paas/developer-cloud/csdmg/migrating-oracle-cloud-infrastructure.html#GUID-C4198FBA-AB5D-4398-89DA-8510728F9E3F" target="_blank">here</a>.<br />
<br />
We executed the following steps:<br />
<ul style="text-align: left;">
<li>Create the Developer Cloud instance in OCI</li>
<li>Create the storage resource for migration of the project</li>
<li>Migrate the project</li>
<li>Add the users</li>
<li>Remove the Developer Cloud Classic instance </li>
</ul>
<br />
<h2 style="text-align: left;">
Create the Developer Cloud instance in OCI</h2>
Because it is not native yet, you can't create the instance using Terraform. The easiest way is to use the user interface:<br />
<ul style="text-align: left;">
<li>Login to OCI</li>
<li>Select "Developer Cloud" from Platform Services</li>
<li>Enter the name you want to use </li>
<li>Add a description and some tags (optional)</li>
<li>Confirm </li>
</ul>
<br />
You can now create the organization properties, by copying them from the Developer Cloud Classic instance or create your project using new properties (which what we did).<br />
<br />
If you are planning to create build jobs in the future (which we are planning for Kubernetes), you need to make a connection to OCI from Developer CS.<br />
<br />
Now we have our Developer Cloud setup, it is time to migrate the stuff from the old instance.<br />
<br />
<h2 style="text-align: left;">
Create storage resource</h2>
The first thing to do when you want to export and import the git repository, is to setup an OCI Object Storage bucket to host the data from the exported project. You can use a common container for all projects, but we recommend keeping separate storage buckets per project.<br />
<br />
To avoid mistakes and make sure we have consistent naming conventions, we use Terraform scripts to create resources. You can find the documentation <a href="https://www.terraform.io/docs/providers/oci/r/objectstorage_bucket.html" target="_blank">here</a>.<br />
<br />
Note: you can skip all the optional fields mentioned, all you need is the compartment_id, the bucket_name and the bucket_namespace.<br />
<br />
We will use a compartment we created for this purpose: DEVCS compartment, and the user, devcs.user with a public and private key, the group and the policies. For more information, see the documentation. Note that in the documentation, separate users and groups are setup for both managing the resources from Developer Cloud Service and reading and writing the data from the storage resource to manage the import and the export. In our case, it did not add much value to have separate users and policies, so we reused the devcs.user for this purpose. This means we din't add the policies because devcs.user can already manage all resources in the compartment.<br />
<br />
<h2 style="text-align: left;">
Move the git repository</h2>
We are now ready to move our git repository. We will migrate the entire project that the git repository is part of.<br />
<ul style="text-align: left;">
<li>Export your project. You find extensive documentation <a href="https://docs.oracle.com/en/cloud/paas/developer-cloud/csdmg/migrate-your-devcs-instance.html#GUID-8321037A-145D-48D5-AFDE-707E816EB0DD" target="_blank">here</a>.</li>
<li>Import the data into a new project. You find extensive documentation <a href="https://docs.oracle.com/en/cloud/paas/developer-cloud/csdmg/migrate-your-devcs-instance.html#GUID-91630640-2507-4F8F-B2E1-201E12F64B96" target="_blank">here</a>.</li>
<ul>
<li>Create project</li>
<li>Import project</li>
</ul>
<li>Add users (those are not migrated, unfortunately)</li>
</ul>
Please make sure you add users to the application role DEVELOPER_USER of the new Developer Cloud Instance in IDCS first. This is a bit hidden in the documentation. Please note that users who have accounts that are locked can't be added to the project. You have to unlock them first. This often occurs because some tool like SourceTree poll the repository. If the password has expired, this leads to a locked account.<br />
<br />
<h2 style="text-align: left;">
Alternative</h2>
Because in our case, we only had a git repository we wanted to migrate, the alternative would have been to skip the export/import step and simply create a new remote git repository in the new project of the new instance and then push the code to that remote.<br />
<br />
How to do that is described <a href="https://help.github.com/en/github/using-git/adding-a-remote" target="_blank">here</a><br />
<br />
So, what is the preferred method? After executing the steps above my recommendation is:<br />
<ul style="text-align: left;">
<li>If you only have a git repository and no Wiki, Jira or build jobs you need to import just create a new project and a new remote git repository</li>
<li>If you have build jobs, Wiki pages, Jira issues that you want to keep, use the import/export methodology described in this blog post.</li>
</ul>
<br />
<h2 style="text-align: left;">
Remove the Developer Cloud Classic instance </h2>
Now that we are done and have the new project up and running, we need to clean up the old instance. The documentation describes how to do that <a href="https://docs.oracle.com/en/cloud/paas/developer-cloud/csdmg/complete-migration-tasks.html#GUID-470C2922-96D6-493E-916C-6218AAB8CC06" target="_blank">here</a>.<br />
<br />
Happy coding 😀</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-21065949613918125272019-09-20T01:09:00.004+02:002019-09-20T09:02:41.649+02:00Upgrade your kubeconfig in Oracle Cloud Infrastructure to version 2.0.0<div dir="ltr" style="text-align: left;" trbidi="on">
On September 16th, Oracle sent out a notification about a change that needs action before November 15th 2019: you need to upgrade your kubeconfig file from version 1.0.0 to version 2.0.0<br />
<br />
Unfortunately, the links in the mail don't describe how to upgrade it, just how to download it....<br />
<br />
So here is a short blog that describes what I did on my machine to upgrade my kubecofig file.<br />
<br />
<h3 style="text-align: left;">
Update the config file</h3>
<ol style="text-align: left;">
<li>open a command window</li>
<li>type oci -v</li>
<li>If the version is 2.6.4 or higher, you are fine. Otherwise type: pip install oci-cli --upgrade Take a look at this page if you encounter issues: <a href="https://docs.cloud.oracle.com/iaas/Content/API/SDKDocs/cliupgrading.htm" target="_blank">Upgrading the CLI</a></li>
<li>type oci ce cluster create-kubeconfig --cluster-id [your cluster ocid] --file $HOME/.kube/config --region [your region] --token-version 2.0.0 </li>
</ol>
<br />
The response should be:
<br />
<pre style="overflow-wrap: break-word; white-space: pre-wrap;"><code><span style="font-family: inherit; font-size: large;">
</span></code></pre>
<pre style="overflow-wrap: break-word; white-space: pre-wrap;"><code><span style="font-family: inherit; font-size: medium;">Existing Kubeconfig file found at C:\Users\ldikmans/.kube/config and new config merged into it</span></code></pre>
<pre style="overflow-wrap: break-word; text-align: left; white-space: pre-wrap;"><code>
</code></pre>
<h3 style="text-align: left;">
Test the new config</h3>
Please make sure you test your configuration by starting your proxy and open a browser that points to it:<br />
<br />
<br />
<ol style="text-align: left;">
<li>Open a command window</li>
<li>Type kubectl proxy</li>
<li>Open a browsser window</li>
<li>Add the URL: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login</li>
<li>Select your updated kubeconfig file</li>
</ol>
<br />
<h3 style="text-align: left;">
Fix problems</h3>
<br />
If you get the error "Not enough data to create auth info structure." , follow these steps:<br />
<br />
<ol style="text-align: left;">
<li>open a command prompt</li>
<li>type kubectl get secrets -n kube-system</li>
<li>type kubectl describe secret -n kube-system kubernetes-dashboard-token-jjtzg (or whatever your dashboard service account user has as a token)</li>
<li>copy the resulting token</li>
<li>open the browser </li>
<li>Add the URL: http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/login</li>
<li>Select "Token"</li>
<li>Paste the token you copied in step 4 in the field for token</li>
</ol>
<div>
When the dashboard opens properly, store the token in a file so you can copy it in the next time.</div>
<div>
<br /></div>
<md-icon aria-label="warning" class="material-icons" role="img"></md-icon>Now you are all set!<br />
<br />
<div>
Happy coding 😀<br />
<br />
<br />
<br />
ps: I would have been nice if this instruction was in the mail Oracle sent. Unfortunately it points to a link that contains the regular installation that does not explain it will merge it automatically. The good news is it was easier than it looked!<br />
<br />
ps2: I think you should be able to store the token in the config file as well. However, so far I did not manage to make this work in my environment.</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-6745039816718061742019-09-15T04:30:00.003+02:002019-09-15T04:30:38.488+02:00Building a docker image and pushing it to the Docker hub using Oracle Developer Cloud<div dir="ltr" style="text-align: left;" trbidi="on">
Oracle Developer Cloud offers some powerful features to automate your build and deployment process to support CI/CD (continuous integration/ continuous delivery)<br />
The nice part is that you don't have to use the Oracle docker registry or git repository (although you can of course), you can use Github repositories and Docker hub.<br />
<br />
This post describes how I built and pushed my docker image with a node.js backend to docker hub, fetching the code from Github.<br />
<h2 style="text-align: left;">
Prequisites</h2>
You need the following to follow the steps in this blog:<br />
<ol style="text-align: left;">
<li>Github account with a repository containing an application. Note that you could also build any type of docker image, but my examples I assume node.js</li>
<li>Docker hub account that can store your images</li>
<li>Oracle Cloud tenancy that you are administrator of the OCI part</li>
<li>A Developer cloud instance setup with your OCI details (see <a href="https://docs.oracle.com/en/cloud/paas/developer-cloud/csdcs/service-setup.html#GUID-994ABF40-4096-4944-B8FE-9597242C10C0" target="_blank">Dev CS documentation</a>)</li>
</ol>
<h2 style="text-align: left;">
Setup your VM template and create Build VM</h2>
<div>
The build VM that you will use for this, needs to be able to build docker. So you need to create a new VM template with the following software installed on it:</div>
<div>
<br />
<ul style="text-align: left;">
<li>Go to "Organization" and click on "Virtual Machine Templates"</li>
<li>Click on "Create Template"</li>
<li>Put a name and a description and select Linux 7</li>
<li>Click "Create"</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioSDx8aGwTCi3p3VDFda7TBwq15XUgg66V-yH-jn0_8nHo3iLAzKSDHylMqXO7G-EipRqEF1ZwK4EE4nPPcLD7unGaldkZMA9-q2A25D4DoOO2sZYUlCLuvXWwT8cPc5l_foxosjUO4j4/s1600/Docker+VM+template+create.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="414" data-original-width="802" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEioSDx8aGwTCi3p3VDFda7TBwq15XUgg66V-yH-jn0_8nHo3iLAzKSDHylMqXO7G-EipRqEF1ZwK4EE4nPPcLD7unGaldkZMA9-q2A25D4DoOO2sZYUlCLuvXWwT8cPc5l_foxosjUO4j4/s320/Docker+VM+template+create.PNG" width="320" /></a></div>
<div>
<br /></div>
<ul style="text-align: left;">
<li>Click on "Configure Software"</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfVg2AWSIboctUNmMP6ecnlaJyaCihgmxZJc4-DnL5cRvi2W0cd6O958vme4HusUICJ3u0stEs6Go4LN7YunXv3WZLEASovLtEioWQF-WqR8a0ZeORwLz7Hdfwribf_fDy4sMJbjjmUAo/s1600/Configure+Software.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="913" data-original-width="1531" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfVg2AWSIboctUNmMP6ecnlaJyaCihgmxZJc4-DnL5cRvi2W0cd6O958vme4HusUICJ3u0stEs6Go4LN7YunXv3WZLEASovLtEioWQF-WqR8a0ZeORwLz7Hdfwribf_fDy4sMJbjjmUAo/s320/Configure+Software.PNG" width="320" /></a></div>
<div>
<br /></div>
<ul style="text-align: left;">
<li>Select "Docker 17.2"</li>
<li>Click on "Done"</li>
</ul>
<div>
You now have a VM template. This template will be used to create your build VM</div>
<div>
<ul style="text-align: left;">
<li>Click on Build Virtual Machines</li>
<li>Click on "Create VM"</li>
<li>Select the quantity (1), the template you just created, the region you want the VM to be in and the shape of the VM you need (in my case I used VM Standard 1.1)</li>
<li>Click Add</li>
</ul>
<div>
You now have a build VM that can be used to build docker images and push them to docker hub (or the OCI registry)</div>
</div>
<div>
<br /></div>
<h2 style="text-align: left;">
Setup your docker repository</h2>
<div>
Because we are not pushing to the Oracle Registry but to Docker hub, you have to setup your docker registry link:</div>
<div>
<ul style="text-align: left;">
<li>Click on "Project Administration"</li>
<li>Click on "Repositories"</li>
<li>Click on "Link External Docker Registry"</li>
<li>Put the name of your registry (lonneke in my case)</li>
<li>Put the link of the docker hub. Please note you have to put "https://registry-1.docker.io/"</li>
<li>Write a description and enter your username and password</li>
<li>Click "Create"</li>
</ul>
<div>
You can check the link by going to the "Docker" tab in your project. It should list your current repositories in your docker hub account.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN8R7-yCYIHqB_EIksWlHrCyM1_2CSgMbUXB87_BJXGsZmbjCkto2xnOadVH-uS5SvLWgfSpyg2GnQr0-6ehFp0Kwc-eaXylIwhRXypVim-AWoh61edG7ax0KUD4N4v8Ny4XmrVm6wMMo/s1600/dockerrepositories.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="906" data-original-width="1546" height="187" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN8R7-yCYIHqB_EIksWlHrCyM1_2CSgMbUXB87_BJXGsZmbjCkto2xnOadVH-uS5SvLWgfSpyg2GnQr0-6ehFp0Kwc-eaXylIwhRXypVim-AWoh61edG7ax0KUD4N4v8Ny4XmrVm6wMMo/s320/dockerrepositories.PNG" width="320" /></a></div>
<br /></div>
</div>
<div>
<br /></div>
<h2 style="text-align: left;">
Define the build job</h2>
<div>
Now that we have done the setup, we can define the build job. We will define a job that will checkout the code from github, build the docker image, login to docker and then pushes it to docker hub.</div>
<h3 style="text-align: left;">
Create job</h3>
<div>
First we need to create a job</div>
<div>
<div>
<ul>
<li>Click Create Job</li>
<li>Put the name of the job (build shipment-backend-ms for example)</li>
<li>Select the template we just created</li>
</ul>
</div>
</div>
<h3 style="text-align: left;">
Configure Git</h3>
<div>
Now we configure git, so the right code gets checked out.</div>
<div>
<ul style="text-align: left;">
<li>Put the repository link that you can copy from github (https://github.com/ldikmans/blockchain-shipping-soaring-clouds-sequel.git) </li>
<li>Optionally put the branch (develop)</li>
<li>Click Save</li>
</ul>
<h3 style="text-align: left;">
Define Build image</h3>
</div>
<div>
<ul style="text-align: left;">
<li>Click on Steps</li>
<li>Select "Docker" from the dropdown in steps and select "Docker build"</li>
<li>Select the registry host you define before when you created the external link</li>
<li>Put the image name and optionally a version tag</li>
<li>Put the context root (in my case shipping/backend/src/node) where you want the docker image to be built from</li>
</ul>
<div>
Now we add the login step to be able to push to the registry</div>
</div>
<div>
<ul style="text-align: left;">
<li>Click on "Add Step"</li>
<li>Select "Docker" from the drop down and select "Docker login"</li>
<li>Select the registry host from the drop down that we just created</li>
<li>Put the username and password that needs to be used</li>
</ul>
<div>
Last but not least we push the image to docker hub:</div>
</div>
<div>
<ul style="text-align: left;">
<li>Click on "Add Step"</li>
<li>Select "Docker" from the drop down and select "Docker push"</li>
<li>Select the registry host you define before when you created the external link</li>
<li>put the same name and image tag as you did in the build step</li>
<li>Click save</li>
</ul>
<div>
We are now ready to run the build</div>
</div>
</div>
<div>
<br /></div>
<h2 style="text-align: left;">
Run the build job</h2>
<div>
Go to the build overview and select your job<br />
<ul style="text-align: left;">
<li>click on "build now"</li>
<li>After a while the build will start. The first time it can take a bit longer because the VM needs to be started</li>
<li>Once the build is started, you can follow the progress by Clicking on "Build log</li>
</ul>
Once the build is done, you can check the images by clicking on "Docker" in the project. Your new image should be listed!<br /><ul style="text-align: left;">
</ul>
<div>
Now the next step is that we run a build every time we do a merge request to develop and deploy the image to kubernetes using the build jobs. I will save that for some other time</div>
<div>
<br /></div>
<div>
Happy coding 😀</div>
</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-45019487079366846602019-08-27T23:07:00.002+02:002020-06-19T13:50:48.215+02:00Deploy Oracle Blockchain SDK on Oracle Cloud Infrastructure<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on"><i>[EDITED JUNE-18-2020, UPDATE TO INSTALL DOCKER, WITH SPECIAL THANKS TO MATHIJS KEMP]</i></div><div dir="ltr" style="text-align: left;" trbidi="on"><br /></div><div dir="ltr" style="text-align: left;" trbidi="on">
In my previous post I described how to write a chaincode for Oracle Blockchain Cloud Service. Sometimes you don't have access to the blockchain cloud service, or you want to test your blockchain locally without deploying it to your production instance.<br />
<br />
For that use case, there is good news: you can deploy it on Oracle Cloud Infrastructure.<br />
<br />
To make this work you need to do the following:<br />
<br />
<ol style="text-align: left;">
<li>Create a compartment for your blockchain (for example SDKBLOCKCHAIN)</li>
<li><a href="https://docs.cloud.oracle.com/iaas/Content/GSG/Tasks/creatingkeys.htm" target="_blank">Create a public/private key pair</a></li>
<li>Create a VCN </li>
<li>Create a compute instance</li>
<li>Install docker</li>
<li>Build the SDK</li>
<li>Create blockchain instance (founder)</li>
</ol>
<h2 style="text-align: left;">
Create the VCN</h2>
<div>
see <a href="https://docs.cloud.oracle.com/iaas/Content/Network/Tasks/managingVCNs.htm">https://docs.cloud.oracle.com/iaas/Content/Network/Tasks/managingVCNs.htm</a> for a detailed explanation of this service in Oracle Cloud Infrastructure.</div>
<div>
<br /></div>
<div>
For this purpose, we create a VCN and related resources. </div>
<div>
<br /></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9PDeOpZtYtMwcW7Yjvjpm9JS7IRJ68yNO-l93P5cEd77wL7AyzPaP1eKl7G9Rl98877wdylyLzclObiCfkH1TeEunnuvXM8JTXZl_7pfzVrkQF4_KHTlpHq49_tcwoRbfh5hDlAMJd78/s1600/createVCN.PNG" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="819" data-original-width="937" height="348" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh9PDeOpZtYtMwcW7Yjvjpm9JS7IRJ68yNO-l93P5cEd77wL7AyzPaP1eKl7G9Rl98877wdylyLzclObiCfkH1TeEunnuvXM8JTXZl_7pfzVrkQF4_KHTlpHq49_tcwoRbfh5hDlAMJd78/s400/createVCN.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">create VCN dialog in Oracle Cloud Infrastructure</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
Next we open up the ports for this VCN so the blockchain console ports are accessible from the internet</div>
<div>
<br /></div>
<div>
<ul style="text-align: left;">
<li>Click on security lists</li>
<li>Click on the default security list</li>
<li>Make sure the provisioning page is accessible from the internet by opening port 3000</li>
<li>Make sure that 500 ports are accessible from the internet (the blockchain SDK will take up to 500 ports)</li>
</ul>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJEBQitBAa99M95cDMdlRczjKHHVifi76k-BuqhYSrewJD_-PFoPcVGP7WKh3Yx4oBgcUc3Yr9BzUAjVu4IKxT0qBaCIYsSTCYbq3Kc4inb3Z40aFqYZHYWqjGdS2rRpnV4s7oPdc3gag/s1600/Ingress+Rule.PNG" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="530" data-original-width="992" height="212" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjJEBQitBAa99M95cDMdlRczjKHHVifi76k-BuqhYSrewJD_-PFoPcVGP7WKh3Yx4oBgcUc3Yr9BzUAjVu4IKxT0qBaCIYsSTCYbq3Kc4inb3Z40aFqYZHYWqjGdS2rRpnV4s7oPdc3gag/s400/Ingress+Rule.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Ingress rule for ports of Blockchain Console<br />
<br /></td></tr>
</tbody></table>
</div>
<div>
<br /></div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
The list of rules should look like this:<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjahhbPk-UDkHHzNhXJCcGQU7lAYbbIdkVJ-UuGc0UUNqs-OrEVPL0fZZg6P4uo4a7JBy1E5KzaUlkJe-GpAqMCNhD9jc7Ql51HE6Hu0J9R8dT633rn1CUpEiKq5LrM5wFk3Od4S-10Xaw/s1600/allrules.PNG" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="612" data-original-width="1566" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjahhbPk-UDkHHzNhXJCcGQU7lAYbbIdkVJ-UuGc0UUNqs-OrEVPL0fZZg6P4uo4a7JBy1E5KzaUlkJe-GpAqMCNhD9jc7Ql51HE6Hu0J9R8dT633rn1CUpEiKq5LrM5wFk3Od4S-10Xaw/s400/allrules.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">List of Ingress rules for SDK VCN<br />
<br />
<br /></td></tr>
</tbody></table>
<br /></div>
<div>
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<div dir="ltr" style="text-align: left;" trbidi="on">
<br /></div>
<h2 style="text-align: left;">
Create the Compute instance</h2>
<div dir="ltr" style="text-align: left;" trbidi="on">
Create a compute instance that complies with the following values:</div>
<br />
<table class="tg" style="border-collapse: collapse; border-color: rgb(204, 204, 204); border-spacing: 0px; table-layout: fixed; width: 902px;"><colgroup><col style="width: 94px;"></col><col style="width: 254px;"></col><col style="width: 554px;"></col></colgroup><tbody>
<tr><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: normal; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Attribute</th><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: normal; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Value</th><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: normal; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Remark</th></tr>
<tr><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Linux Version</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">7.3</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">or higher</td></tr>
<tr><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Linux kernel</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">3.10</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">or higher</td></tr>
<tr><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">RAM</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">4GB</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">or higher</td></tr>
<tr><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Storage</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">30GB</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">build.sh -d <> >=12GB Ensure there's enough space to unpack the package.Workspace<br />
build.sh -w [] >=5GB Workspace is relating to the transaction <br />
volume. For a clean installation, at least 5G of free space is <br />
recommended./var/lib >=10GB For a clean installation, Oracle <br />
Blockchain Platform SDK Docker images consume approximately 8GB /var/lib<br />
space.</td></tr>
<tr><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">CPU</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">2</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">or higher</td></tr>
<tr><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">hostname</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">[compute instance].[subnet].[dns vcn]</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">internal FDQN</td></tr>
<tr><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">IP</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">xxx.xx.xx.xxx</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">public IP of your instance</td></tr>
</tbody></table>
</div>
</div>
<br />
<h4 style="text-align: left;">
Set the timezone TZ variable</h4>
Make sure that you set the TZ variable in your profile, otherwise you will get an error when provisioning the blockchain instance.<br />
<br />
<ul style="text-align: left;">
<li>vi .bash_profile file</li>
<li> Add TZ='Europe/Amsterdam'; export TZ to the file</li>
<li>Save and quit (wq)</li>
<li> Log out</li>
<li>Log in</li>
</ul>
<h4 style="text-align: left;">
Disable the firewall</h4>
<br />
Check if the firewall is running: sudo firewall-cmd --state<br />
<div>
<span style="font-family: "courier new", courier, monospace;">running</span><br />
If it is running, stop it:<br />
<code><span style="font-family: "courier new", courier, monospace;">sudo systemctl disable firewalld</span></code><br />
run the command again: <span style="font-family: "courier new", courier, monospace;">sudo firewall-cmd --state</span><br />
<span style="color: red; font-family: "courier new", courier, monospace;">not running</span><br />
<span style="color: red; font-family: "courier new", courier, monospace;"><br /></span>
<span style="font-family: inherit;">You can of course update the firewall instead of disabling it, I was too lazy to type that up today 😁</span><br />
<span style="font-family: inherit;"><br /></span></div>
<h2 style="text-align: left;">
Install Docker</h2>
<div><ol class="ak-ol" data-pm-slice="3 3 []"><li><p>Execute the following commands to install some required packages:</p><pre><code>sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
sudo yum install -y yum-utils device-mapper-persistent-data lvm2</code></pre></li><li><p>Add the repository</p><pre><code>sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo</code></pre></li><li><p>Install the docker community edition</p><pre><code>sudo yum install docker-ce docker-ce-cli containerd.io</code></pre></li><li><p>Start docker and enable the start of docker on boot</p><pre><code>sudo systemctl enable --now docker.service</code></pre></li><li><p>Check the version of docker</p><pre><code>sudo docker version</code></pre><p>Run hello world to see if docker is installed correctly</p><pre><code>docker run hello-world</code></pre><p></p></li></ol></div><div>
<br />
<h2 style="text-align: left;">
<span style="font-family: inherit;">Build the Instance</span></h2>
<div style="text-align: left;">
Now we are ready to install the SDK</div>
<div style="text-align: left;">
<br /></div>
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li><a href="https://www.oracle.com/technetwork/topics/cloud/downloads/blockchain-sdk-5443939.html" target="_blank">Download </a>it from the Oracle website </li>
<li>Unzip to /usr/local/bcssdk</li>
<li>Run sudo ./build.sh This will run it with all the default:</li>
</ul>
</div>
<div>
<br /></div>
</div>
<table class="tg" style="border-collapse: collapse; border-color: rgb(204, 204, 204); border-spacing: 0px;"><tbody>
<tr><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Option</th><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Attribute</th><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Value</th></tr>
<tr><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">-d</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">package directory</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">/usr/local/bcssdk</td></tr>
<tr><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">-w</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">provision workspace directory</td><td style="background-color: white; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">~/obcs_worksapce</td></tr>
<tr><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">-p</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">provision console port</td><td style="background-color: #f9f9f9; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">3000</td></tr>
</tbody></table>
<br />
<h2 style="text-align: left;">
Create Instance</h2>
<div>
<br />
<ul style="text-align: left;">
<li>Open the console: http://[IP ADDRESS]:3000</li>
<li>Chose a username and password for your provisioning application and click ok</li>
<li>This opens the console and you can create a founder with the following attributes:</li>
</ul>
</div>
<div>
<table class="tg" style="border-collapse: collapse; border-color: rgb(204, 204, 204); border-spacing: 0px;"><tbody>
<tr><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Attribute</th><th style="background-color: #f0f0f0; border-color: inherit; border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Value</th></tr>
<tr><td style="background-color: #f9f9f9; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">Instance name</td><td style="background-color: #f9f9f9; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">name you picked</td></tr>
<tr><td style="background-color: white; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">host name</td><td style="background-color: white; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">internal FQND</td></tr>
<tr><td style="background-color: #f9f9f9; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">start port</td><td style="background-color: #f9f9f9; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">port you opened in ingress</td></tr>
<tr><td style="background-color: white; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">founder</td><td style="background-color: white; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">yes</td></tr>
<tr><td style="background-color: #f9f9f9; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">authorization</td><td style="background-color: #f9f9f9; border-color: rgb(204, 204, 204); border-style: solid; border-width: 0px; color: #333333; font-family: arial, sans-serif; font-size: 14px; overflow: hidden; padding: 10px 5px; text-align: left; vertical-align: top; word-break: normal;">yes</td></tr>
</tbody></table>
<div>
<br />
The username password will be set to admin/Welcome1 when you check the "Authorization" box. The result can be seen below</div>
<div>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkeks4-JSeyw1sbIOMHfT1Xj7x_HWh-rFgVeXMclre7fPPVgICAuMCm9WbPPvJHMy4f5O9KQ0Fh0Gg2Jge2N6g6IAbdab256gl1p_Cdsa9AALjwEV-u1zPZt661NaNNKon4uWCH1m_Y74/s1600/provisionInstance.PNG" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="Picture shows the values of the created instance" border="0" data-original-height="181" data-original-width="553" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjkeks4-JSeyw1sbIOMHfT1Xj7x_HWh-rFgVeXMclre7fPPVgICAuMCm9WbPPvJHMy4f5O9KQ0Fh0Gg2Jge2N6g6IAbdab256gl1p_Cdsa9AALjwEV-u1zPZt661NaNNKon4uWCH1m_Y74/s400/provisionInstance.PNG" title="" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Provision instance after building the SDK</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
</div>
<br /></div>
<h2 style="text-align: left;">
Finally</h2>
<div>
Click on the name. This will open a browser, but it will say "not found". Replace the FQDN with the IP address, and leave the port.<br />
<br />
When you do that, it warns about the certificate. Accept that and it prompts for username password.<br />
Login using admin/Welcome1 and you will see your blockchain console!<br />
<br />
http://[IP ADDRESS]:21003<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfFJMmY2-BE_Ub9lE5i1focUaiKcJ_RQiWzq2DpFrfP9MKsbuhVCf4HraVWjcdga269ZcO-IOjBzy35jPhKrkVRPZAd2JVG115YzAXlnJaHOBkh-Tk_We4zw0u5eMj3z8ubAJ8z7oEvc4/s1600/blockchainconsole.png" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="263" data-original-width="553" height="190" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgfFJMmY2-BE_Ub9lE5i1focUaiKcJ_RQiWzq2DpFrfP9MKsbuhVCf4HraVWjcdga269ZcO-IOjBzy35jPhKrkVRPZAd2JVG115YzAXlnJaHOBkh-Tk_We4zw0u5eMj3z8ubAJ8z7oEvc4/s400/blockchainconsole.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Blockchain console after creating the instance</td></tr>
</tbody></table>
<br /></div>
<div>
<br /></div>
<div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Happy coding 😀</div>
<div>
<br /></div>
</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-39002854135331100792019-03-30T22:59:00.003+01:002019-03-30T22:59:36.019+01:00Oracle BlockChain Service: creating a smart contract aka how to write a chaincode<div dir="ltr" style="text-align: left;" trbidi="on">
In the <a href="http://blog.vennster.nl/2017/10/my-first-blockchain-in-oracle-cloud.html" target="_blank">first blog</a> about blockchain, I used Oracle Compute Cloud Classic and installed MultiChain on it. Since then, Oracle has released a Blockchain Cloud Service with a lot of out of the box functionality, based on <a href="https://www.hyperledger.org/" target="_blank">Hyperledger</a>.<br />
<br />
In this blog post I will describe how to create a smart contract for a webshop use case: getting offers from different suppliers for a specific order. I already know node.js so I will write the ChainCode in node. Note that go is also supported.<br />
<br />
<h3 style="text-align: left;">
Prerequisites</h3>
<ul style="text-align: left;">
<li>A running instance of Oracle Blockchain Service</li>
<li>Node.js installed on your laptop</li>
</ul>
<div>
There are a number of steps involved in writing a smart contract (or chaincode).</div>
<div>
<ol style="text-align: left;">
<li>Design the chaincode</li>
<li>Write a chaincode (in Node)</li>
<li>Deploy a ChainCode to a Peer </li>
<li>Test the chaincode with Postman</li>
</ol>
</div>
<h3 style="text-align: left;">
Design </h3>
<div>
Before you write a chaincode, you need to know what transactions need to be supported. In our example we have a webshop, that issues requests for shipping after ordering an item. Shippers can create an offer. If they are selected by the customer, they pickup the shipment. The customer receives the goods at the end of the cycle. For more information about designing the chaincode, see the <a href="https://hyperledger-fabric.readthedocs.io/en/release-1.4/developapps/architecture.html" target="_blank">hyperledger documentation</a></div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4nNdnCLqzwhxjpdmXUIolELHq9pB-gBadXLWpOJWsovRIf-eEISjiVTl-BlZpzfwUawi18eqHetURdKsc6N0-DGqkC0nEaRO7CDtJ0wkc2jfnWHJMLII2KZugDNaM9JCu5bcmEBswvx4/s1600/DesignShipping.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="703" data-original-width="1534" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg4nNdnCLqzwhxjpdmXUIolELHq9pB-gBadXLWpOJWsovRIf-eEISjiVTl-BlZpzfwUawi18eqHetURdKsc6N0-DGqkC0nEaRO7CDtJ0wkc2jfnWHJMLII2KZugDNaM9JCu5bcmEBswvx4/s320/DesignShipping.png" width="320" /></a></div>
<div>
<br /></div>
<h3 style="text-align: left;">
Write a ChainCode</h3>
<div>
The easiest way to write the chaincode is to download an example from the Oracle BlockChain Service and modify it.<br />
<br />
<ol style="text-align: left;">
<li>Navigate to the Blockchain console and click on Developers tools.</li>
<li>Click on Download oracle samples</li>
<li>Download the Cardealer sample and unzip it</li>
<li>Navigate to [yourpath]\CarDealer\artifacts\src\github.com\node and copy cardealer_cc</li>
<li>Paste the cardealer_cc in a new folder where you want to store your code and rename it to shipment_cc</li>
<li>Leave the methods Init and Invoke as is and create methods to issue, offer, select, pickup and receive a shipment. </li>
</ol>
<br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;">---------------<b>code snippet</b>--------------------------------</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"> <span style="font-size: x-small;">shipment.orderId = args[0];</span></span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.product = args[1].toLowerCase();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.customer = args[2].toLowerCase();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.shippingAddress = args[3];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.orderDate = parseInt(args[4]);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if (typeof shipment.orderDate !== 'number') {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> throw new Error('5th argument must be a numeric string');</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.custodian = args[5].toLowerCase();</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.currentState = shState.ISSUED;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> shipment.offers = [];</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // ==== Check if shipment already exists ====</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let shipmentAsBytes = await stub.getState(shipment.orderId);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> if (shipmentAsBytes.toString()) {</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> console.info('This shipment already exists: ' + shipment.orderId);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> jsonResp.Error = 'This shipment already exists: ' + shipment.orderId;</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> throw new Error(JSON.stringify(jsonResp));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // ==== Create shipment object and marshal to JSON ====</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> let shipmentJSONasBytes = Buffer.from(JSON.stringify(shipment));</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> // === Save shipment to state ===</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> await stub.putState(shipment.orderId, shipmentJSONasBytes);</span></div>
</div>
<div>
<br /></div>
<br />
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><b> -------------end code snippet --------------------------</b></span></div>
<br />
<h3 style="text-align: left;">
Deploy the chaincode</h3>
</div>
<div>
After writing the chaincode, it needs to be deployed to the blockchain. In this example we will deploy it to the shipment channel using the quick start. This will instantiate it and use the default endorsement policy. Please note that channels and chaincodes can't be deleted after creating and deploying them.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<ol style="text-align: left;">
<li>Zip the code and the package.json in a zip</li>
<li>Click on "Deploy a new Chaincode" in the chaincode menu in the blockchain console.</li>
<li>Click on Quick Deployment</li>
<li>Fill out the right details</li>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXkeCyP_nZijbODADvgbZpX6RSlfqvYdVLWZoquiMMv7wsRiu1XW0NSIkbSrN76rMWGYcXY7E_p2ATlTSqtcaFcIkIMzZlIoICuNXlcGBsV8mtrMIlDe0uNHy9FqwSU87l86qtXGhNZI4/s1600/DeployChaincode.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="812" data-original-width="899" height="288" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjXkeCyP_nZijbODADvgbZpX6RSlfqvYdVLWZoquiMMv7wsRiu1XW0NSIkbSrN76rMWGYcXY7E_p2ATlTSqtcaFcIkIMzZlIoICuNXlcGBsV8mtrMIlDe0uNHy9FqwSU87l86qtXGhNZI4/s320/DeployChaincode.PNG" width="320" /></a></div>
<div>
<br />
<br />
<br />
<br />
<li>Upload the zipfile and wait until the dialog shows that the chaincode is instantiated and deployed succesfully. </li>
<li>Enable the rest proxy by going to the chaincode and clicking on the hamburger menu. Click on "Enable on REST Proxy". </li>
<li>Fill out the fields as shown in the figure below</li>
</div>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCTsTgQVfsnMe_Xy29fRtQuYUy2ZZpXxCgx2XKrYmwc69zg3JFdoYTk7q44ADN_QOtbmgOIk7J6qVMiMK5a9YX81N0dghn89GlTYc2L8t7NrNS8N26Fadw3a9deFZSANNjemXon4vJBw/s1600/EnableRESTProxy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="588" data-original-width="919" height="204" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgPCTsTgQVfsnMe_Xy29fRtQuYUy2ZZpXxCgx2XKrYmwc69zg3JFdoYTk7q44ADN_QOtbmgOIk7J6qVMiMK5a9YX81N0dghn89GlTYc2L8t7NrNS8N26Fadw3a9deFZSANNjemXon4vJBw/s320/EnableRESTProxy.PNG" width="320" /></a></div>
<div style="text-align: left;">
<br /></div>
<h3 style="text-align: left;">
Test the chaincode</h3>
<ol style="text-align: left;"><div>
</div>
</ol>
</div>
<div style="text-align: left;">
Now that we have deployed the chaincode, we can test it using the REST proxy. Before you do this, make sure you have the right role associated with your user (<code class="codeph" style="background-attachment: inherit; background-clip: inherit; background-color: white; background-image: inherit; background-origin: inherit; background-position: inherit; background-repeat: inherit; background-size: inherit; border-radius: 4px; box-sizing: border-box; color: #333333; font-family: "Courier New", Courier, monospace; font-size: 15.4px; padding: 0px;">RESTPROXY4_USER</code><code class="codeph" style="background-attachment: inherit; background-clip: inherit; background-color: white; background-image: inherit; background-origin: inherit; background-position: inherit; background-repeat: inherit; background-size: inherit; border-radius: 4px; box-sizing: border-box; color: #333333; font-size: 14px; padding: 0px;"><span style="font-family: "helvetica neue" , "segoe ui" , "roboto" , , sans-serif;">)</span></code></div>
<div>
<ol style="text-align: left;">
<li>Open postman</li>
<li>Create a new "Post request" to issue a shipment</li>
<li>Go to the blockchain console and find the URL that is listed for the RESTProxy that you enabled for your chaincode</li>
<li>Create a request that looks as follows: </li>
</ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">curl -X POST \</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> https://restserver:port/restproxy4/bcsgw/rest/v1/transaction/asyncInvocation \</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> -H 'Authorization: Basic xxx' \</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> -H 'Content-Type: application/json' \</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> -H 'cache-control: no-cache' \</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> -d '{</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>"args":[1,"iron","John Doe","Rembrandtlaan 22c Bilthoven","0330","webshop"],</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>"channel": "testshipping",</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>"chaincode": "shipment",</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>"chaincodeVer":"1.0",</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><span style="white-space: pre;"> </span>"method": "issueShipment"</span><br />
<ol style="text-align: left;"></ol>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">}'</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: normal;">The result should like this:</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-size: x-small;"></span><br />
<div style="font-family: "Courier New", Courier, monospace;">
<span style="font-size: x-small;">{</span></div>
<span style="font-size: xx-small;">
</span>
<div style="font-family: "courier new", courier, monospace; font-size: small;">
<span style="font-size: xx-small;"> "returnCode": "Success",</span></div>
<span style="font-size: xx-small;">
<div style="font-family: "courier new", courier, monospace; font-size: small;">
"txid": "a4f5e851734f7e3ebdfa0761bfd54bab090cdaf08266363fe2451eacc3a14826"</div>
<div>
<div style="font-family: "courier new", courier, monospace; font-size: small;">
}</div>
</div>
</span>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<div>
<div style="text-align: left;">
</div>
<h4 style="text-align: left;">
Next steps</h4>
You can now query the result of this transaction, read the shipment etc.<br />
<br />
Happy coding! 😃</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-44661064312422651662019-01-21T22:36:00.001+01:002019-01-22T13:31:28.277+01:00Another blockchain: installing Ethereum on Oracle Cloud<div dir="ltr" style="text-align: left;" trbidi="on">
After installing MultiChain on Oracle Compute Cloud, and playing around with HyperLedger on the Oracle Blockchain Cloud service, I now ran into a case where Ethereum was used.<br />
<br />
This blog post describes how I installed a Ethereum node on Oracle Cloud Infrastructure.<br />
<br />
<h3>
Prerequisites</h3>
<div>
<ul>
<li>An account on Oracle Cloud with Administrator rights</li>
<li>You have generated an <a href="https://docs.cloud.oracle.com/iaas/Content/GSG/Tasks/creatingkeys.htm" target="_blank">ssh key-pair</a></li>
<li>You are logged in to your cloud account</li>
</ul>
</div>
<h4>
</h4>
<h4>
</h4>
<h4>
Create Compartment</h4>
Create a compartment with the name Ethereum to separate this from your other infrastructure. You can find this under "Identity".<br />
<h4>
</h4>
<h4>
</h4>
<h4>
Create a Virtual Cloud Network</h4>
<div>
<ol>
<li>Navigate to Virtual Cloud Network, by selecting Network from the Menu</li>
<li>Select the compartment you just created</li>
<li>Click "Create Virtual Cloud Network"</li>
</ol>
<ul>
<li>The compartment will default to the compartment you just selected</li>
<li>Name: ethereum-network</li>
<li>select "Create Virtual Cloud Network plus related resources" to quickly get up and running</li>
<li>Click "Create"</li>
</ul>
A dialog is displayed that shows you what has been created, after a few seconds.</div>
<h4>
</h4>
<h4>
</h4>
<h4>
Create compute nodes</h4>
<div>
For this example I will create 3 nodes on 3 separate VMs.</div>
<div>
<ol>
<li>Go to the Compute Menu</li>
<li>Select "Ethereum" in the compartment dropdown (left side of the menu)</li>
<li>Click Create Instance</li>
<li>Give the instance a name (ethereum-node1 for example)</li>
<li>Leave all the defaults for shape and OS</li>
<li>Upload your public key</li>
<li>Select the networking you created (ethereum-network)</li>
<li>Click "Create"</li>
</ol>
<div>
Repeat this process for 2 more nodes (giving them separate names of course).</div>
</div>
<div>
<br /></div>
<div>
You should have three nodes now, like the picture below shows. It might take a couple of minutes before they are completely done, but not longer than 5 minutes.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyhypTgSXRnDH_wnbHtvP3U5hn2wg33wPt7AqNJAUZSi_dc3PMXNkD1u7CuxvYwKTUGEXx6G6i1qoqQpiED0Cw6L_S8qCpErGtcgEbVcQdTu64Y9I01O2KUuM_14doVeRYozcWcFlyZSk/s1600/3nodes.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="582" data-original-width="1600" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjyhypTgSXRnDH_wnbHtvP3U5hn2wg33wPt7AqNJAUZSi_dc3PMXNkD1u7CuxvYwKTUGEXx6G6i1qoqQpiED0Cw6L_S8qCpErGtcgEbVcQdTu64Y9I01O2KUuM_14doVeRYozcWcFlyZSk/s400/3nodes.PNG" width="400" /></a></div>
<div>
<br /></div>
<h3>
</h3>
<h3>
</h3>
<h3>
</h3>
<div>
<br /></div>
<div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
You can connect to your instance as "opc" using the private key and the public IP address that is published in the console.</div>
<h3>
</h3>
<h3>
Install Ethereum</h3>
<div>
To install Ethereum for Oracle Enterprise Linux, you have to install it from source. There is no package available.</div>
<div>
<br /></div>
You need git, go and gcc. The easiest way is to install development tools<br />
<br />
<ul>
<li></li>
<li>sudo /usr/bin/ol_yum_configure.sh</li>
<li>sudo yum update</li>
<li>sudo yum groupinstall 'Development Tools'</li>
<li>sudo yum install gettext-devel openssl-devel perl-CPAN perl-devel zlib-devel</li>
<li>sudo yum install curl-devel</li>
</ul>
<br />
<ul>
</ul>
<div>
<h4 style="text-align: left;">
Install git</h4>
</div>
<ul>
<li>sudo wget https://github.com/git/git/archive/v2.10.1.tar.gz -O git.tar.gz</li>
<li>tar -zxf git.tar.gz</li>
<li>cd git-2.10.1/</li>
<li>make configure</li>
<li>./configure --prefix=/usr/local</li>
<li>sudo make install</li>
<li>git --version to check the installation</li>
</ul>
<br />
<ul>
</ul>
<div>
<h4 style="text-align: left;">
Install go</h4>
</div>
<div>
<ul>
<li>cd ~</li>
<li>wget https://dl.google.com/go/go1.11.4.linux-amd64.tar.gz</li>
<li>sudo tar -C /usr/local -xzf go1.11.4.linux-amd64.tar.gz</li>
<li>add go to your path by editing .bash_profile</li>
<li>go version to check the installation</li>
</ul>
<br />
<ul>
</ul>
</div>
<h4 style="text-align: left;">
Install geth</h4>
<div>
To create the private network, we need to install geth, the command line tool that runs a ful Ethereum node implemented in Go. It offers three interfaces: </div>
<div>
<ol>
<li>the command line subcommands and options</li>
<li>a Json-rpc server</li>
<li>An interactive console</li>
</ol>
<div>
Execute the following commands</div>
</div>
<div>
<ul>
<li>cd ~</li>
<li>git clone https://github.com/ethereum/go-ethereum</li>
<li>cd go-ethereum</li>
<li>make geth</li>
<li>add build/bin to your path by editing your .bash_profile</li>
</ul>
<br />
<ul>
</ul>
</div>
<h4>
Start the node</h4>
<div>
You can start a node by running build/bin/geth. This will add this node to the public ethereum network. This node is now part of the Ethereum network.<br />
<br />
<br />
If you don't want to be part of the public network, you can also create a private network. <a href="https://github.com/ethereum/go-ethereum/wiki/Private-network">https://github.com/ethereum/go-ethereum/wiki/Private-network</a>.<br />
<br />
<br /></div>
<div>
Happy coding 😊</div>
<div>
<br /></div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-61348176558772312972018-12-05T14:43:00.001+01:002018-12-05T14:43:28.287+01:00Node.js musings part I: node version management<div dir="ltr" style="text-align: left;" trbidi="on">
I started programming at a very young age, when I was twelve. My first programming language was Basic. I wrote a program that would generate random calculation problems in different categories (under 10, under 100). If the answer given by the user was incorrect, a picture based on 10 x 10 squares would show the correct answer visually.<br />
It was actually used by a remedial teacher (my mom 😉) on our home computer.<br />
<br />
Since then I learned a language comparable to Pascal, I used LISP in university, took classes in C, C++, MFC, Visual Basic and Java.<br />
<br />
The next software I wrote was after I graduated, for a marketing department. They showed calculations of how much water a water closet or shower would use in different languages. I wrote it in Visual Basic. That was the first time I learned about the hassle of versions in real life.<br />
The program ran fine on my Windows machine (I think it was Windows 95). But on the sales persons machine it would not print. The library was incompatible with my compiled code. I was in 'DLL hell' 😱 as my professor used to call it.<br />
<br />
I stayed away from procedural language and decided to focus on Java and JEE. I loved it! No issues with native libraries, object orientation to structure your code, automated builds, test frameworks etc etc.<br />
Of course, I was involved in multiple projects. Some projects would support Java version 1.4 others 1.5 etc. First I started having different versions on my machine and updating environment variables, but quickly I would need application servers etc as well, so I started creating Virtual Images for Virtual Box and have different versions of the JDK and application versions there.At least I had no issues with native libraries, like I remembered from Visual Basic! It was not ideal, but I managed and felt in control.<br />
<br />
Today we are doing more and more projects in the (Oracle) Cloud. We are doing projects in Oracle SOA CS, Oracle Integration Cloud Service, Oracle API Platform Cloud Service and Oracle Mobile Cloud Service.<br />
Oracle Mobile Cloud Service is expecting node.js code for the mobile backend functions that you write. This meant I had to learn JavaScript. Not everything was easy from the start: The asynchronous nature of Node was something I definitely had to get used to. <span style="font-family: Courier New, Courier, monospace;">asynch</span>/<span style="font-family: Courier New, Courier, monospace;">await</span> to the rescue ;)<br />
The beauty: no more application servers, no more multiple VMs for different versions: just code! So far so good. :)<br />
<br />
Then, we moved to a different version of the cloud service and upgraded our node version to version 8.11.3. and happily start using the new version. I think right now we are on version 11. Of course this does not have a happy end: a week ago I started investigating Oracle BlockChain Cloud Service. It expects node version 6 😰. And now I am back in version hell: node.js uses specific native libraries under the covers, that of course are not the same between the different versions. I need to be able to switch between versions. Some projects expect the paths to be pointing to the right versions and of course constructs like <span style="font-family: Courier New, Courier, monospace;">await</span> are not supported, so running my code in Netbeans becomes complicated...<br />
<br />
<h3 style="text-align: left;">
nvm-win to the rescue</h3>
<div>
I was considering creating images for Virtual Box again (also because I still like bash better than windows Powershell), but I decided to research the topic a little bit. I stumbled upon this project: <a href="https://github.com/coreybutler/nvm-windows" target="_blank">nvm-windows</a></div>
<div>
<br /></div>
<div>
It look really good: I can switch versions without having to fiddle around with the path or environments myself, it is all managed by this package that is written in go (another language I might want to learn, but one thing at the time ;) )</div>
<div>
<br /></div>
<div>
Here is how to install it on Windows:</div>
<div>
<ol style="text-align: left;">
<li>Uninstall node from your local machine. Remove all folders related to it C:\Users\{username}\AppData\Roamding\npm and C:\Users\{username}\AppData\Roamding\npm-cache</li>
<li>Download nvm-setup.zip</li>
<li>Unzip it</li>
<li>Run nvm-setup and accept the defaults</li>
<li>Open a new Powershell window and type <span style="font-family: Courier New, Courier, monospace;">nvm</span></li>
<li><span style="font-family: inherit;">It will show the version (1.1.7 in my case)</span></li>
<li><span style="font-family: inherit;">Install the versions of node you need. In my case</span></li>
<ol>
<li><span style="font-family: Courier New, Courier, monospace;">nvm install 6</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">nvm install 8</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">nvm install latest</span></li>
</ol>
</ol>
</div>
<div>
<span style="font-family: inherit;">You can now list your versions, and use the one you would like to use by typing</span></div>
<div>
<ul style="text-align: left;">
<li><span style="font-family: Courier New, Courier, monospace;">nvm list</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">nvm use 6.15.1</span></li>
</ul>
<div>
<span style="font-family: inherit;">I am not sure I love Node.js and javascript as much (yet) as I love Java, but it might happen in the future ....</span></div>
<div>
<span style="font-family: inherit;"><br /></span></div>
<div>
<span style="font-family: inherit;">Any comments and pointers on how you deal with versions of node are much appreciated, please feel free to comment on this blog or tweet them!</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;">Happy coding 😏</span></div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-72486308461347314292018-12-03T23:51:00.001+01:002018-12-03T23:59:17.680+01:00Setting up fn on Kubernetes in the Oracle Cloud (OKE)<div dir="ltr" style="text-align: left;" trbidi="on">
In this post I will briefly describe how you can install <a href="https://github.com/fnproject/fn-helm/" target="_blank">fn </a>on Kubernetes in the Oracle Cloud (<a href="https://www.oracle.com/webfolder/technetwork/tutorials/obe/oci/oke-full/index.html" target="_blank">OKE</a>).<br />
<br />
<h3 style="text-align: left;">
Prerequisites</h3>
<div style="text-align: left;">
</div>
<ol style="text-align: left;">
<li>You need to have access to Oracle Cloud Infrastructure (OCI) with a unique account. If you have a federated account, you should create another one to be able to create a kubernetes cluster. This account must have either Administrator privileges or belong to a group to which a policy grants the appropriate Container Engine for Kubernetes permissions. Since my example is for R&D purposes, I will be using an account with Administrator privileges.</li>
<li>Install and configure the OCI CLI, generate an API signing key pair and add that public key to your username. </li>
<li>Create a separate compartment for the cluster and make sure your compartment has the necessary resources and your root compartments needs the policy <code style="box-sizing: border-box; font-family: "Courier New", Courier, monospace; font-size: 15.4px; text-indent: -17px;">Allow service OKE to manage all-resources in tenancy</code><span style="font-family: "helvetica neue" , "segoe ui" , "roboto" , , sans-serif; font-size: 14px; text-indent: -17px;"> </span></li>
<li><span style="text-indent: -17px;"><span style="font-family: inherit;">Install and setup kubectl on Windowns (tip: use <a href="https://chocolatey.org/" target="_blank">Chocolatey</a>)</span></span></li>
<li><span style="text-indent: -17px;"><span style="font-family: inherit;">Install <a href="https://github.com/helm/helm#install" target="_blank">helm</a></span></span></li>
</ol>
<h3 style="text-align: left;">
Create the Kubernetes cluster</h3>
<div>
<ol style="text-align: left;">
<li>Navigate to your console</li>
<li>Under Developer Services, select "clusters"</li>
<li>Pick the compartment that you created or want to use</li>
<li>Click on "Create Cluster" and accept all the defaults</li>
<li>Click "Create"</li>
<li>Inspect the details </li>
<li>Download the kubeconfig file and store it in your .kube directory</li>
</ol>
If it fails because of service limits, raise an SR with Oracle support to get your limits increased.</div>
<div>
<br /></div>
<h3 style="text-align: left;">
Install fn </h3>
<div>
<ol style="text-align: left;">
<li>Make sure your server version of helm is up to date (<span style="font-family: "courier new" , "courier" , monospace;">helm init --upgrade</span>)</li>
<li>Create a directory fnhelm</li>
<li>Clone the git repo: <span style="font-family: "courier new" , "courier" , monospace;">git clone https://github.com/fnproject/fn-helm.git</span></li>
<li>Install the chart dependencies: helm dep build fn</li>
<li>Install it in your cluster: helm install --name my-release fn</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihJMNX8ffQQYiyP4abzSfEq3tIDOcklOoV3WMsrDPmxxmYC96Yga_SeRO-0ptLyRiBAAsrkYzfr06hYuNuql5r4wYgDgYhZHBS8_Z1SDIlhF1jv_lE5ESDvK9zMm9xEu0Jp1Arm_5mJNo/s1600/fnChart.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="698" data-original-width="1600" height="173" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihJMNX8ffQQYiyP4abzSfEq3tIDOcklOoV3WMsrDPmxxmYC96Yga_SeRO-0ptLyRiBAAsrkYzfr06hYuNuql5r4wYgDgYhZHBS8_Z1SDIlhF1jv_lE5ESDvK9zMm9xEu0Jp1Arm_5mJNo/s400/fnChart.PNG" width="400" /></a></div>
<div>
<br /></div>
<h3 style="text-align: left;">
Deploy your function to the cluster</h3>
</div>
<div>
<ol style="text-align: left;">
<li>Make sure you are logged in to your dockerhub account</li>
<li>Set the fn context to the right value</li>
<li>Deploy the function to the cluster</li>
</ol>
<div>
<br /></div>
</div>
<h4 style="text-align: left;">
The fn context</h4>
<div>
When you use fn deploy, it uses a context to determine where to deploy to, and what registry to use. The URL for the fnserver you deployed to the kubernetes cluster can be found by issuing the following command<br />
<br /></div>
<div>
<ul style="text-align: left;">
<li><span style="font-family: Courier New, Courier, monospace;">$(kubectl get svc --namespace default my-release-fn-api -o jsonpath='{.status.loadBalancer.ingress[0].ip}'):80</span></li>
</ul>
<div>
However, you can also look it up using a kubectl proxy: </div>
<ul style="text-align: left;">
<li><span style="font-family: "courier new" , "courier" , monospace;">kubectl proxy</span> </li>
<li>Navigate to a browser: https://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#</li>
<li>Select "Services" in the navigation menu at the left</li>
</ul>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr8HzYLayb6ZAotGpGR2-HAVYL2QFuceVSps1Iza2mvsSA4YOvIgk1CxbhKznpGXg3mPbq6FQOiyYGnt_g0jBeNCFD9BztRsE2GaYXU4MQ7E7LlaSZgQ22HljkX5mdG_EiVqcNsTbHSSg/s1600/kubernetesProxy.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="788" data-original-width="1600" height="196" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr8HzYLayb6ZAotGpGR2-HAVYL2QFuceVSps1Iza2mvsSA4YOvIgk1CxbhKznpGXg3mPbq6FQOiyYGnt_g0jBeNCFD9BztRsE2GaYXU4MQ7E7LlaSZgQ22HljkX5mdG_EiVqcNsTbHSSg/s400/kubernetesProxy.PNG" width="400" /></a></div>
<div>
<br /></div>
<ul style="text-align: left;">
<li>Click on the External Endpoint of the my-release-fn-api </li>
<li>You should see the following:</li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZc-y_ktbyx5wSDanq2IKMId8llsacDY_L0KvDlXlNlgxLK2GDuMCoGKWbaPBRJU1QMR_LIaJ8eiFdfdT8HZK0m371cBf7Lpx4eagMP8nXof8PjkE-pPNUg6Eoi5-eY8W6ka_hfw41myw/s1600/result.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="198" data-original-width="560" height="141" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjZc-y_ktbyx5wSDanq2IKMId8llsacDY_L0KvDlXlNlgxLK2GDuMCoGKWbaPBRJU1QMR_LIaJ8eiFdfdT8HZK0m371cBf7Lpx4eagMP8nXof8PjkE-pPNUg6Eoi5-eY8W6ka_hfw41myw/s400/result.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
Now we can create the context by running the following commands:</div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul style="text-align: left;">
<li><span style="font-family: "courier new" , "courier" , monospace;">fn list contexts</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">fn create context ociLonneke --api-url [your url] --provider default --registry [your_dockerhub_username]</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">fn list contexts</span></li>
</ul>
<div>
<br /></div>
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div>
<h4 style="text-align: left;">
Deploy the function to the cluster</h4>
<div>
Finally! We are ready to deploy our first function to our cluster. In this case I use the Java tutorial example. </div>
<div>
<ul style="text-align: left;">
<li><span style="font-family: Courier New, Courier, monospace;">fn init --runtime java --trigger http javafn</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">fn build</span></li>
<li><span style="font-family: "courier new" , "courier" , monospace;">fn deploy --app java-app</span></li>
</ul>
<div>
This will result in the following output (or something similar)</div>
</div>
<div>
<br /></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Successfully created app: java-app</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Successfully created function: javafn with lonneke/javafn:0.0.2</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Successfully created trigger: javafn-trigger</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">Trigger Endpoint: http://xxx.xx.xx.xx:80/t/java-app/javafn-trigger</span></div>
</div>
<div>
<br /></div>
<h3 style="text-align: left;">
Test the function</h3>
<div>
Open a browser and type the url as stated by the trigger endpoint. You should see the following result:</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyMP4swOJza3eSWcLyRkvfUdZcTkYo6lJeC51SohbmCjjMV3q7vKJW4jXRY0-RDXHPDil3W3ldO5A6KHi6NHGhq68NgkethDQacmlktmzzsUI2TmSFnEAyWFnzqsjDAhovs0CQGORHvRo/s1600/resultFunction.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="278" data-original-width="842" height="131" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhyMP4swOJza3eSWcLyRkvfUdZcTkYo6lJeC51SohbmCjjMV3q7vKJW4jXRY0-RDXHPDil3W3ldO5A6KHi6NHGhq68NgkethDQacmlktmzzsUI2TmSFnEAyWFnzqsjDAhovs0CQGORHvRo/s400/resultFunction.PNG" width="400" /></a></div>
<h3 style="clear: both; text-align: left;">
Next steps</h3>
<div class="separator" style="clear: both; text-align: left;">
Now you have your kubernetes cluster up and running, you can move your functions from your local installation to the cluster and start using them in production!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Happy coding 😊</div>
<div>
<br /></div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<div style="text-align: left; text-indent: -17px;">
<br /></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br /></div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-69395438709286555772018-10-23T20:22:00.003+02:002018-10-23T20:36:55.947+02:00Even Aces make mistakes: Reuse<div dir="ltr" style="text-align: left;" trbidi="on">
Every year Debrah Lilley is kind enough to round up a couple of Oracle Aces to talk about projects, and/or new features at Oracle Open World.<br />
This year we present a session with 9(!) people about our 'favorite' mistake we made and what we learned from it.<br />
<br />
From the summary:<br />
<div style="text-align: left;">
<span style="background-color: white; color: #444444;"><i><span style="font-family: inherit;">"A quick diversion from our now traditional featured short talks, this year our EMEA ACE Directors will share their biggest errors and what they learned from it. A fast, fun session that will energize you on your Oracle OpenWorld 2018 experience."</span></i></span></div>
<div style="text-align: left;">
<span style="background-color: white; color: #444444;"><i><span style="font-family: inherit;"><br /></span></i></span></div>
<div style="text-align: left;">
<span style="color: #444444;"><span style="background-color: white;">I have five minutes to talk about my favorite mistake, so this blog post elaborates on the topic a bit more.</span></span></div>
<div style="text-align: left;">
<span style="color: #444444;"><span style="background-color: white;"><br /></span></span></div>
<h2 style="text-align: left;">
<span style="color: #444444;"><span style="background-color: white;">Reuse</span></span></h2>
<div style="text-align: left;">
In software, we like to reuse code. This enhances productivity, it minimizes the chance of introducing new mistakes and gives us a chance to focus on the new things we are trying to accomplish, instead of reinventing the wheel. This has been a very strong driver of Service Oriented Architecture (SOA). </div>
<div style="text-align: left;">
There are multiple ways of implementing or realizing reuse:</div>
<div style="text-align: left;">
</div>
<ul style="text-align: left;">
<li>create a runtime component that you call from your code to do the job ('a service')</li>
<li>create a library or code that you share from a central location and import in your code ('a common artifact in SOA Suite in MDS, or a library in Java or Node.js)</li>
<li>a pattern ('template') that you apply as a best practice </li>
<li>a copy (!?) of the code you want to reuse and adapt. </li>
</ul>
<div>
One of the downsides of reuse, is flexibility loss. If you are reusing something, a change to it will impact all the consumer or users of that piece of code. service etc. This is why micro services architecture is all about bounded contexts and decoupling using events. </div>
<div>
<br /></div>
<div>
In SOA there has been a very common misconception: the fact that reuse is good, no matter what, resulting in inflexible very complex code that is expensive to change and, in the end, hard to reuse (!)</div>
<div>
This particularly happens a lot with canonical models, and yes, I made that mistake too.</div>
<div>
<br /></div>
<div>
Let's go back in time, to a project where we created an application for the province of Overijssel for permits and grants, using Oracle SOA Suite 11g, a content management. The solution basically consisted of 4 different composites (Apply, Process, Decide, Notify), the Oracle Servicebus, a content management system, SAP ERP, a permit application and a.NET user interface.</div>
<div>
<br /></div>
<div>
For the integration between the .NET interface and the BPEL process support, we designed a canonical model.<br />
<br />
<h4 style="text-align: left;">
Canonical model side note</h4>
</div>
<div>
<br /></div>
<div>
The picture below shows what a canonical mode is supposed to do: make sure that <b>in the servicebus and between applications</b>, a canonical model is used.</div>
<div>
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjPcXl85mIpPSGzChlH7w6sCghss4Gs8gGVv2jzjCFKWCpiAwaBfi62as6k9Xo6uzsbLlV2oL4VCTkyjCJIJuqqRTiEuME-2_i0nLpf3c2pmr7wFCOX7sHjN78hnmeES2aB9kDP_217hY/s1600/canonical+model.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="410" data-original-width="1600" height="101" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgjPcXl85mIpPSGzChlH7w6sCghss4Gs8gGVv2jzjCFKWCpiAwaBfi62as6k9Xo6uzsbLlV2oL4VCTkyjCJIJuqqRTiEuME-2_i0nLpf3c2pmr7wFCOX7sHjN78hnmeES2aB9kDP_217hY/s400/canonical+model.png" width="400" /></a></div>
<div>
<h4 style="text-align: left;">
</h4>
<div>
<br /></div>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
End of side note</h4>
</div>
<div>
<br />
However, we decided to use the canonical model inside of our BPELs as well. This had several advantages:<br />
<ol style="text-align: left;">
<li>we did not have to design the WSDL and XML Schemas for the BPEL</li>
<li>we could assign the entire message to the BPEL input and output variables</li>
</ol>
<br />
<h3 style="text-align: left;">
Change</h3>
We were done very fast, but we found we needed a number of changes in the canonical model to facilitate the .NET application. They wanted different structures and different fields. None of these had any functional impact on process flow, since the BPEL was mostly driving the process, adding approvals, enrichments and fetching and storing data in the correct backend system.<br />
However, because we used the canonical model in all of our BPELs, we had to redo all of our assignments and xslts to pick up this new version, making sure nothing changed in the flow and functionality of the component.<br />
The change cost the same amount of time as the inital realization, because the work in BPEL is not in clicking together the scopes, but in building the logic in the assignments and xslts.<br />
<br />
<h2 style="text-align: left;">
Lessons learned</h2>
We learned a number of things from this particular approach:<br />
<br />
<ol style="text-align: left;">
<li>Separation of concerns matters. This has been a long standing IT and computer science principle. See for example <a href="https://www.blogger.com/(https://en.wikipedia.org/wiki/Separation_of_concerns)" target="_blank">(https://en.wikipedia.org/wiki/Separation_of_concerns)</a>. There is a reason you put different groups in your electrical wiring in your house: if one of the groups fails, the other parts of the house are unaffected. When you have to make a change for a specific purpose, you should have to make that change in one place only. In case of the canonical model, in the <b>servicebus and the components that are calling the servicebus.</b></li>
<li>Reuse has an impact on changeability and maintainability. To make sure things can be changed, apply the tolerant reader pattern (<a href="https://www.blogger.com/Tolerant%20reader%20pattern%20(https://martinfowler.com/bliki/TolerantReader.html)" target="_blank">(https://martinfowler.com/bliki/TolerantReader.html)</a></li>
<li>Pick your reuse pattern carefully: a pattern you want to reuse (or a template), a library that you will apply, a service that you want to call, or creating a copy to be quick, but that you will be able to change independently.</li>
<li>Don't send data to systems that don't care about it. In this case were were sending data and dragging it along in the BPEL that were not needed in the BPEL. Typically all you need in the BPEL are identifiers and dates. Then, when you need more data in a specific scope, you can fetch it from the appropriate source. </li>
</ol>
<div>
We refactored the code and made specific WSDLs and XSDs for all BPELs and used the canonical model in the OSB, where it belongs. </div>
<div>
It became a lot easier to work with the messages in the BPEL and changes in the UI had no or little impact on the process, as they should!</div>
<div>
<br /></div>
<h2 style="text-align: left;">
Code smells</h2>
</div>
<div>
So how do you know if you are reusing the canonical model too much. These are some tell tales that point in that direction:</div>
<div>
<br /></div>
<h3 style="text-align: left;">
SOA Suite</h3>
<div>
<ol style="text-align: left;">
<li>You have to redeploy 'MDS' everytime a new feature is defined</li>
<li>All your artefacts (WSDLs, XSDs, DVMs) are in MDS, there are no 'local composite' artefact</li>
<li>You have a lot of data in your messages in BPEL that are in none of the assigns or in only one of the assigns</li>
<li>You have a lot of merge conflicts with other teams that are working on completely different topics</li>
<li>You have a if statements in your BPEL that never merge back into 1 common flow, based on something in your canonical model</li>
</ol>
</div>
<h3 style="text-align: left;">
Java, Javascript</h3>
<div>
<ol style="text-align: left;">
<li>Your ORM library gets updated all the time and your code needs to change because of it.</li>
<li>You filter out values and fields in most of your code</li>
<li>You are extending the common objects to add your own behavior and attributes and filter out the common behavior. </li>
</ol>
</div>
<h2 style="text-align: left;">
Conclusion</h2>
<div>
Reuse is a powerful and important topic to be productive and to avoid mistakes. However, reuse is not a goal, it is a means to an end. Modern systems need to be changeable in the first place. Reuse should be carried out within the context as appropriate. Global models should be treated carefully and be minimized to where they add value and are needed. </div>
<div>
We can all learn from domain driven design principles and microservices architectures in our other architectures as well to make sure we don't paint ourselves into a corner!</div>
<div>
<br /></div>
<div>
Happy coding 😎</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-69328566428100499152017-12-10T14:57:00.000+01:002017-12-10T14:57:06.955+01:00Troubleshooting Oracle API Platform Cloud Service<div dir="ltr" style="text-align: left;" trbidi="on">
One of the challenges when working in integration is troubleshooting. This becomes even more challenging with when you start using a new product.<br />
<br />
Recently I worked with Oracle Product management (Thank you Darko and Lohit) to troubleshoot issues with an OAuth configuration of APIs in Oracle API Platform Cloud Service.<br />
<br />
<h4 style="text-align: left;">
Setup</h4>
The setup was as follows:<br />
<ol style="text-align: left;">
<li>An API Gateway node deployed to Oracle Compute Cloud Classic as an infrastructure provider</li>
<li>Oracle Identity Management Cloud Service in the role of OAuth provider</li>
</ol>
<div>
We setup an API with several policies, including OAuth for security. When we called the service, it gave us a '401 unauthorized' error.<br />
<br /></div>
<h4 style="text-align: left;">
Oracle API Platform Cloud Service troubleshooting</h4>
<div>
The Oracle API Platform Service offers analytics for each API. You can navigate there by opening the API Platform Management portal, click on the API you want to troubleshoot and click on the Analytics tab (this is the bottom tab).<br />
<br />
Click on Errors and Rejections, after setting the period you are interested in. Usually when you are troubleshooting, you would like to see the last hour.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlVA5fW_Ei65K6NrLKLzrVWBrNyMxPsWcg9bL9zWi24VRuzp4mGEBeaFfUDpZjCKRRnNLBj-rJDvAsTG-UMmdgUwfrIJ2nlX3_nJPDdT4Zc8Lzy2sKLcKELaQGGJPOslqP5wWG4Z6hmA0/s1600/errorsAndRejectsion.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="771" data-original-width="1600" height="154" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlVA5fW_Ei65K6NrLKLzrVWBrNyMxPsWcg9bL9zWi24VRuzp4mGEBeaFfUDpZjCKRRnNLBj-rJDvAsTG-UMmdgUwfrIJ2nlX3_nJPDdT4Zc8Lzy2sKLcKELaQGGJPOslqP5wWG4Z6hmA0/s320/errorsAndRejectsion.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Different type of analytics in an API</td></tr>
</tbody></table>
<br /></div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Now you can scroll down to error distribution and see the errors that occurred. In this case, because I selected "Last Week" you see a number of different errors that occurred last week and how often they occurred. When you run your test again, you will see one of the errors in the distribution increase, giving you insight in the type of error.<br />
<div style="text-align: left;">
<br /></div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-Lk9j_oLZr2hSImKZEX7G77JYLLsJSYCLhIUITC3FMGP3hJpjsFrh3wbyVdJCJv8UD6zZ6OgIy1yuwY8UkKilF3_rC3pUZ20aVwYxQ-EZaNRqwlwHfjgm7KtX5Rn9kD1_9p1Xn4f4ChA/s1600/rejection+distribution.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="630" data-original-width="1600" height="125" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj-Lk9j_oLZr2hSImKZEX7G77JYLLsJSYCLhIUITC3FMGP3hJpjsFrh3wbyVdJCJv8UD6zZ6OgIy1yuwY8UkKilF3_rC3pUZ20aVwYxQ-EZaNRqwlwHfjgm7KtX5Rn9kD1_9p1Xn4f4ChA/s320/rejection+distribution.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Distribution of each error type</td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
We tried different configurations, as you can see from the distribution, the graph tells us that the OAuth token was invalid and that in another case we had a bad JWT key. This mean we had to take a look at the configuration of the OAuth profile of the Oracle API Gateway Node. (see the <a href="https://docs.oracle.com/en/cloud/paas/api-platform-cloud/apfad/configuring-oauth-providers.html" target="_blank">documentation</a> on how to configure Oracle Identity Cloud Service as OAuth provider).<br />
<br />
<h4 style="text-align: left;">
OAuth token troubleshooting </h4>
<div style="text-align: left;">
We had a token, but it appeared to be invalid. It is hard to troubleshoot security: what is wrong with our configuration? Why are we getting the erors that we get? When you successfully obtain an OAuth token, you can inspect it with JSON Web Toolkit Debugger. </div>
<div>
<ol style="text-align: left;">
<li>Navigate to <a href="https://jwt.io/">https://jwt.io</a></li>
<li>Click on Debugger</li>
<li>Paste the token in the window at the left hand side</li>
</ol>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEpP-F2BRuZZU06OuoyWg71fAPDw4SrkXNK74DWH87kKFYD_lvRaNNo4oamm0gQXsAHAhF1tcFRSpYKIpBWfT8VfjET9DtBml342KaRSCde7jSc89penORKCY7r4cTMwMe5WPLeC3xOJM/s1600/JWT.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="722" data-original-width="1600" height="144" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhEpP-F2BRuZZU06OuoyWg71fAPDw4SrkXNK74DWH87kKFYD_lvRaNNo4oamm0gQXsAHAhF1tcFRSpYKIpBWfT8VfjET9DtBml342KaRSCde7jSc89penORKCY7r4cTMwMe5WPLeC3xOJM/s320/JWT.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">JWT debugger with default token example</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
The debugger shows you a header, the payload and the signature.</div>
</div>
<div>
<br /></div>
<div>
<i>Header </i></div>
<div>
Algorithm that is used, for example SHA256 and types supported (JWT for example)</div>
<div>
<i>Payload </i></div>
<div>
The claim is different per type. There are three types: public, private or registered. A registered claim contains fields like iss (issuer, in this case https://identity.oraclecloud.com/ ), sub (subject), aud (audience) etc. See for more information: <a href="https://tools.ietf.org/html/rfc7519#section-4.1">https://tools.ietf.org/html/rfc7519#section-4.1</a></div>
<div>
<i>Signature</i></div>
<div>
The signature of the token, to make sure nobody tampered with it.</div>
<div>
<br /></div>
<div>
Now you can compare that to what you have put in the configuration of Oracle Identity Management Cloud and the configuration of the Oracle API Gateway Node.</div>
<h4 style="text-align: left;">
<br /></h4>
<h4 style="text-align: left;">
Oracle API Platform Gateway Node trouble shooting</h4>
<div>
Apart from looking at the token and the analytics it can help to look at the log files on the gateway node. The gateway node is an Oracle WebLogic Server with some applications installed on it.<br />
<br />
There are several log files you can access.<br />
<ol style="text-align: left;">
<li>apics/logs. In this directory you find the apics.log file. It contains stacktraces and other information that help you troubleshoot the API.</li>
<li>apics/customlogs. If you configured a custom policy in your API, the logfiles will be stored in this directory. You can log the content of objects that are passed in this API. See the <a href="https://docs.oracle.com/en/cloud/paas/api-platform-cloud/apfad/implementing-apis.html#GUID-324A2F7B-AABB-49B4-8F7C-7BBDD882EA53" target="_blank">documentation</a> about using Groovy in your policies for information about the variables that you can use. </li>
<li>'Regular' Managed server logs. If something goes wrong with the connection to the Derby database, or other issues occur that have to do with the infrastructure, you can find the information in /servers/managedServer1/logs directory.</li>
</ol>
</div>
<h4 style="text-align: left;">
Summary</h4>
<div>
When troubleshooting APIs that you have configured in Oracle API Platform cloud service you can use the following tools:</div>
<div>
<ul style="text-align: left;">
<li><a href="http://jwt.io/">jwt.io</a> Debugger. This tool lets you inspect OAuth tokens generated by a provider.</li>
<li>Oracle API Platform Cloud Service Analytics. Shows the type of error.</li>
<li>Oracle API Platform logging policies you put on the API. Lets you log the content of objects. </li>
<li>Log files in the API Gateway node:</li>
<ul>
<li>{domain}/apics/logs for the logs of the gateway node. Contains stracktraces etc</li>
<li>{domain}/apics/customlogs for any custom logs you entered in the api</li>
<li>{domain}/servers/managedServer1/trace for default.log of the managed server</li>
</ul>
</ul>
</div>
<div>
Happy coding!</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-88811914910477548262017-11-30T13:26:00.000+01:002017-11-30T13:29:46.261+01:00Sharing Applications within your team in VBCS, PCS and MCS<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Oracle Visual Builder Cloud Service is a so called 'low code' platform to build user interfaces in the cloud, without the need for a IDE or installing and deploying to servers.<br />
<br />
This can be done by a single user, but this can also be used in a team setting.<br />
<br />
Unfortunately it is not very intuitive how you can share different applications within a team. By default, when you create an application, only the person who created it will see it.<br />
<br />
This is different than in other cloud products like MCS and PCS. In MCS you can see all mobile backends, APIs etc once you have the role 'team member'. In MAX applications are visible by anyone with the role MobileEnvironment_Develop<br />
<br />
In PCS you can create spaces to allow sharing of applications.<br />
<br />
<br /></div>
<table style="width: 100%;">
<tbody>
<tr>
<th>Oracle Product</th>
<th>Shared</th>
</tr>
<tr>
<td>Process Cloud Service (PCS)</td>
<td>Either private or shared in a space</td>
</tr>
<tr>
<td>Mobile Cloud Service (MCS)</td>
<td>To users with role teammember</td>
</tr>
<tr>
<td>Mobile Accellerator (MAX)</td>
<td>User that have the role MobileEnvironment_Develop</td>
</tr>
<tr>
<td>Visual Builder Cloud Service</td>
<td>Explicit assignment to users with role teammember</td>
</tr>
</tbody></table>
<br />
<h3 style="text-align: left;">
</h3>
<h4 style="text-align: left;">
How to share your VBCS application</h4>
<ul style="text-align: left;">
<li>Go to the "Home" tab </li>
<li>Flip the card of your application </li>
<li>Put the name of the team member (only existing teammembers show up) </li>
<li>Click + </li>
</ul>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Y5DwF9cffuPnfxyOHE7h2SGwTrM9fhRXumXxSdD1oLe6gM123VhQlaTxXKCfngDiHGQN7yjqEU0m4w84tpJtEzWEDciA5DNqZkGnteGQ4prSMJDDcsQ0rBmNahvAXIXKHyWBkzXWeHk/s1600/shareApplication.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="511" data-original-width="1191" height="85" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg6Y5DwF9cffuPnfxyOHE7h2SGwTrM9fhRXumXxSdD1oLe6gM123VhQlaTxXKCfngDiHGQN7yjqEU0m4w84tpJtEzWEDciA5DNqZkGnteGQ4prSMJDDcsQ0rBmNahvAXIXKHyWBkzXWeHk/s200/shareApplication.PNG" width="200" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifDNmvdf_9SgJi1vu8KMjgjcph_pOY2RsozTMTzzjLJZiG0irwBLUC9n5FUAZc5SP3D6YW_dkHvPhJKHPObuHux5YXgETdI2FLPRr1HyhyphenhyphenYO0C48KX0zfSTAIgAMp9lO5yvVkYutpBYeE/s1600/add+teammember.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="705" data-original-width="1002" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifDNmvdf_9SgJi1vu8KMjgjcph_pOY2RsozTMTzzjLJZiG0irwBLUC9n5FUAZc5SP3D6YW_dkHvPhJKHPObuHux5YXgETdI2FLPRr1HyhyphenhyphenYO0C48KX0zfSTAIgAMp9lO5yvVkYutpBYeE/s320/add+teammember.PNG" width="320" /></a></div>
<div>
<br /></div>
<div>
<br /></div>
The application is now visible for those team members you added.<br />
<br />
<h4 style="text-align: left;">
Conclusion </h4>
The feature is not hard to understand but hard to find. It is not well documented and the concept is implemented differently in different (related) PAAS products.<br />
<br />
<br />
Happy <strike>coding</strike> configuring 😉<br />
<br />
PS: in the <a href="https://docs.oracle.com/en/cloud/paas/app-builder-cloud/csapb/creating-your-web-application.html#GUID-EA4C7FD0-C120-4A90-9482-437A60A1859A" target="_blank">new documenation</a> of VBCS I found a chapter describing this feature, it is improved faster than I can blog! </div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com1tag:blogger.com,1999:blog-1766203392912336249.post-12739952053381470082017-10-02T19:58:00.001+02:002017-10-02T20:05:04.457+02:00My First Blockchain in the Oracle Cloud<div dir="ltr" style="text-align: left;" trbidi="on">
Being an integration person I am very interested in Blockchain architecture as an alternative for 'traditional' integration options like 'Enterprise SOA' and Centralized Master Data Management.<br />
<br />
This blog will not discuss the architecture of blockchain, but describes how you can get started as a developer with blockchain using Oracle Cloud.<br />
<br />
It assumes you have an instance of Oracle Compute Cloud at your disposal and describes how to get started wth <a href="https://www.multichain.com/getting-started/" target="_blank">MultiChain.</a><br />
<br />
I executed the following steps:<br />
<ol style="text-align: left;">
<li>Create two instances of Oracle Compute Cloud</li>
<li>Install MultiChain</li>
<li>Create the first chain</li>
</ol>
<h3 style="text-align: left;">
Create two instances of Oracle Compute Cloud</h3>
<div>
To show the concept of the block chain you need to create at least two nodes. In this case I created two instances of Oracle Compute Cloud Classic. </div>
<div>
<br /></div>
<div>
<ol style="text-align: left;">
<li>Login to your identity domain: cloud.oracle.com</li>
<li>On the Dashboard, select "Create Instance" and pick "Compute Classic"</li>
<li>This gives you an overview as shown in the figure below. First you need to save the private key to be able to access the instance with ssh. </li>
<ol>
<li>Type a name for the key</li>
<li>Save it on your computer</li>
</ol>
<li>Select "Customize"</li>
<li>Finish the Wizard</li>
<ol>
<li>Select the image "OL_7.2_UEKR4_x86_64"</li>
<li>Select a general purpose shape, unless you are planning to build a real blockchain, then it is recommended to create a High Memory Shape</li>
<li>Add the key you saved to the instance, or upload your own key</li>
<li>For network leave the defaults</li>
<li>Leave defaults in the storage tab </li>
</ol>
<li>You can see the result in the orchestrations tab</li>
</ol>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaX3TQN85ASzT_yvBaI5ojXI4zxGRli6rz5qLThSwV1ZJpIlmNaPGQrTbbq6u0jKjkyv9Ds9KWCwOCKSPMlJna-E1mNO_J0VnDuEJqvg_Y7ewO70Z2hBuIG1FsGM77Vx5lN4yMXwWvTxg/s1600/createInstance.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="728" data-original-width="1600" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgaX3TQN85ASzT_yvBaI5ojXI4zxGRli6rz5qLThSwV1ZJpIlmNaPGQrTbbq6u0jKjkyv9Ds9KWCwOCKSPMlJna-E1mNO_J0VnDuEJqvg_Y7ewO70Z2hBuIG1FsGM77Vx5lN4yMXwWvTxg/s400/createInstance.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Orchestration showing the instances that are created</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<div>
In order to create a chain and have multiple nodes that are aware of each other, you need to make sure the instances can communicate.</div>
<div>
<br /></div>
<div>
To enable this, you need to add a Security Application and a Security Rule for the instances. (Many thanks to <a href="http://www.twitter.com/simon_haslam" target="_blank">Simon Haslam</a> who helped me figure this out!) :</div>
<div>
<br /></div>
<div>
<ol style="text-align: left;">
<li>Click on the Network tab in my instances</li>
<li>Select Shared Network</li>
<li>Select Security Application</li>
<ol>
<li>Create a security Application for te default port</li>
<ol>
<li>Name: TCP2671</li>
<li>Protocol: TCP</li>
<li>Port start: 2671</li>
<li>Port end: 2671</li>
<li>Description: default Multichain port</li>
</ol>
<li>Create a security application for the RPC port</li>
<ol>
<li>Name: TCP2670</li>
<li>Protocol: TCP</li>
<li>Port start: 2670</li>
<li>Port end: 2670</li>
<li>Description: default RPC multichain port</li>
</ol>
</ol>
<li>Select Security Rules</li>
<li>Click Add Security Rule</li>
<li>Fill in the fields</li>
<ol>
<li>TCP2671 for security application</li>
<li>Source: security ip list (public-internet)</li>
<li>Destination: security list (default)</li>
</ol>
<li>Add another security rule for the default RPC port</li>
<ol>
<li>TCP2670 for security application</li>
<li>Source: security ip list (public-internet)</li>
<li>Destination: security list (default)</li>
</ol>
</ol>
<div>
<br /></div>
</div>
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIjN79W4736imiuTr7CNr3jcwzZKu5gpPrsbcTMqE4kUfEk8tYDX5uzQD5hU1kMdvzzSjaXmeLbffk2jXaRSfflokAEcM1CVlx95rJcG7lr7KDY0ytVGJS5JLbDDcDUpE-FbvgpetmjX4/s1600/SecurityApplication.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="490" data-original-width="974" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgIjN79W4736imiuTr7CNr3jcwzZKu5gpPrsbcTMqE4kUfEk8tYDX5uzQD5hU1kMdvzzSjaXmeLbffk2jXaRSfflokAEcM1CVlx95rJcG7lr7KDY0ytVGJS5JLbDDcDUpE-FbvgpetmjX4/s400/SecurityApplication.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY6Nor7AVpVmxQY6cnEgrxMGKVjRSRDGkHiEviZo3V8ieJdIMzVXsf1vdHf4oXjp93f4VWf5GXDF88Lrw6VYjKvAExk-rOdItgioAi9Lv_sEmvj8b-AQhSEpf8FkhrHozuLdy7iNsUhyc/s1600/MultiChainSecurityRule.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="794" data-original-width="984" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiY6Nor7AVpVmxQY6cnEgrxMGKVjRSRDGkHiEviZo3V8ieJdIMzVXsf1vdHf4oXjp93f4VWf5GXDF88Lrw6VYjKvAExk-rOdItgioAi9Lv_sEmvj8b-AQhSEpf8FkhrHozuLdy7iNsUhyc/s400/MultiChainSecurityRule.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
<br /></div>
<div>
Now you are ready to create the second instance. Note that you don't have to set the security rules for new instances, because they are pointing to the default security list in this case. The new instances are added to that automatically. This is of course not something you would do in real life, but for My First Blockchain in the Oracle Cloud it works fine :) </div>
</div>
<div>
<br /></div>
<div>
<br /></div>
<h3 style="text-align: left;">
Install MultiChain</h3>
<div>
You need to install MultiChain on all your instances. </div>
<div>
<br /></div>
<div>
To connect you need a ssh client. I am currently working on a Windows 10 machine, so I use PuTTY. The key that is downloaded from the cloud can't be used directly in PuTTY, you need to import it. </div>
<div>
<ol style="text-align: left;">
<li>Open PuTTYgen</li>
<li>Click import key</li>
<li>Browse to the key you just saved to your computer</li>
<li>Click on "Save Private Key"</li>
<li>Open PuTTY</li>
<li>Enter the details of the instance as shown below and save the session</li>
<ol>
<li>Put in the public IP address of the instance</li>
<li>Point to the SSH private key in the Auth tab</li>
</ol>
<li>Open a session</li>
<li>Install wget: <span style="font-family: "courier new" , "courier" , monospace;">sudo yum install wget -y</span></li>
<li>Run the following in the terminal:</li>
</ol>
<div>
<code style="background: none rgb(255, 255, 255); border-radius: 4px; box-sizing: border-box; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 12.6px; padding: 0px; white-space: nowrap;"></code><br />
<div style="background-color: white; box-sizing: border-box; font-size: 14px; margin-bottom: 10px;">
<code style="background: none; border-radius: 4px; box-sizing: border-box; font-size: 12.6px; padding: 0px; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;">cd /tmp<br style="box-sizing: border-box;" />wget <a href="https://www.multichain.com/download/multichain-1.0.1.tar.gz" style="background: transparent; box-sizing: border-box; text-decoration-line: none;">https://www.multichain.com/download/multichain-1.0.1.tar.gz</a><br style="box-sizing: border-box;" />tar -xvzf multichain-1.0.1.tar.gz<br style="box-sizing: border-box;" />cd multichain-1.0.1<br style="box-sizing: border-box;" />sudo mv multichaind multichain-cli multichain-util /usr/local/bin</span></code></div>
</div>
</div>
<div>
Repeat this for the second instance and if you are testing with more than one, for all the instances you want to include.</div>
<div>
<br /></div>
<h3 style="text-align: left;">
Creating my first chain</h3>
<div>
Now you are ready to start the tutorial to get acquainted with <a href="https://www.multichain.com/getting-started/" target="_blank">MultiChain</a>.</div>
<div>
<br /></div>
<div>
In order to keep track of the different servers, I have given the nodes different colors in my PuTTY sessions.</div>
<div>
<br /></div>
<div>
<ol style="text-align: left;">
<li>Connect to node 1 and execute the commands that are referenced as 'server1' in the tutorial in this window</li>
<li>Connect to node 2 and execute the commands that are references as 'server2' in the tutorial in this window</li>
</ol>
<div>
Note that I need to open two windows of PuTTY for server 2: One to start the node:</div>
</div>
<div>
<br /></div>
<div>
<span style="background-color: white; font-family: "menlo" , "monaco" , "consolas" , "courier new" , monospace; font-size: 12.6px; white-space: nowrap;">multichaind </span><span class="nodeaddress" style="background-color: white; box-sizing: border-box; font-family: "menlo" , "monaco" , "consolas" , "courier new" , monospace; font-size: 12.6px; white-space: nowrap;">chain1@[ip-address]:[port]</span></div>
<div>
<span class="nodeaddress" style="background-color: white; box-sizing: border-box; font-family: "menlo" , "monaco" , "consolas" , "courier new" , monospace; font-size: 12.6px; white-space: nowrap;"><br /></span></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;">And one to start the multichain-cli chain1 interaction. If you don't start the node, you will get an error:</span></span></div>
<div>
<br /></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;">MultiChain 1.0.1 RPC Client</span></span></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;"><br /></span></span></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;"><br /></span></span></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;">Interactive mode</span></span></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;">chain1: getinfo</span></span></div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: "courier new" , "courier" , monospace;">error: couldn't connect to server</span></span></div>
<div>
</div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;">With my two windows open, the interactive client was working like a charm... </span></span><br />
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFQbv6Dm7HjfrBVanX4CnmHsCe93zPcfVpLE5f4DDCUz1YYquSREJe8ZvEM9Hp1gn66NT-FcQpyWhdVNP8qljB_a9hjUlL8H5t1DF87O19MC4nx1ftm-IV0C6QTG4yof6PXUWV03Wt_5w/s1600/TestingMultiChain.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="862" data-original-width="1600" height="215" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiFQbv6Dm7HjfrBVanX4CnmHsCe93zPcfVpLE5f4DDCUz1YYquSREJe8ZvEM9Hp1gn66NT-FcQpyWhdVNP8qljB_a9hjUlL8H5t1DF87O19MC4nx1ftm-IV0C6QTG4yof6PXUWV03Wt_5w/s400/TestingMultiChain.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Three windows testing MultiChain from my windows machine</td></tr>
</tbody></table>
</div>
<div>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span><br />
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;"><br /></span></span>
<span style="background-color: white; white-space: nowrap;"><span style="font-family: inherit;">Happy coding!</span></span></div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-74095778846120464402017-09-07T13:55:00.003+02:002017-09-07T14:22:27.428+02:00Oracle Mobile Cloud Service: team members accessing APIs<div dir="ltr" style="text-align: left;" trbidi="on">
<div dir="ltr" style="text-align: left;" trbidi="on">
Oracle Mobile Cloud Service is setup around different personas. When you login to MCS you see a list of roles.<br />
<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_h1jKkl-k3c1VCEi6gJRt_BO6mXX9yM4P5wZ_ZxmpZW91vTlVGe2dQNlfY_2ibspIbuh9s_1yheM0UEA0yA4tJETS-WAQITO7BwNOSp8Vv9uo7-2jaNVpp1jzAPOaOsWQpwDcR99lnvw/s1600/Capture.PNG" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="862" data-original-width="432" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_h1jKkl-k3c1VCEi6gJRt_BO6mXX9yM4P5wZ_ZxmpZW91vTlVGe2dQNlfY_2ibspIbuh9s_1yheM0UEA0yA4tJETS-WAQITO7BwNOSp8Vv9uo7-2jaNVpp1jzAPOaOsWQpwDcR99lnvw/s320/Capture.PNG" width="160" /></a><br />
The Mobile App developer is the developer that is creating a mobile application and is using APIs that are exposed in MCS. The Service developer is the developer that creates the APIs, connectors etc.<br />
<br />
This distinction is very useful: it helps in making sure the documentation is targeted to the right people and the content is organized in a way that makes sense for these different personas.<br />
<br />
Sometimes, however, it does not work as well. As I discussed in an earlier post: the command line tools to deploy and test services is hidden in software that is targeted at mobile app developers. In this post I want to discuss another use case that is not that obvious apparently: a service developer calling an API.<br />
<br />
In our project we are creating APIs for several different mobile app developers. Before we publish an API and a mobile backend we want to test this mobile backend. We secured the APIs with security roles, because we want to make sure that APIs for internal use are not accidently exposed to external companies. To be able to test the API, we had to assign the correct role to the team member. This is when the challenge started.<br />
<br />
<b>Assigning roles to users in MCS</b><br />
There are two ways of assigning roles to users for MCS. The first method is using the MCS Mobile User Management, which can be accessed using the mobile portal ui:<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoe0XULerm08fqhrv-Q-Hojtnx-t7XcBgogWdDH2uzVwjJyJImV99Jjw8b6t9tceIBMD4sMXSu_wA0cpeUlf8Cdwv5kF0JV6RShJ2Vlugu_LIHgLYWM3_cbSJCz7DUcHdgaBoF-KZPhwE/s1600/Capture.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="916" data-original-width="1541" height="237" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgoe0XULerm08fqhrv-Q-Hojtnx-t7XcBgogWdDH2uzVwjJyJImV99Jjw8b6t9tceIBMD4sMXSu_wA0cpeUlf8Cdwv5kF0JV6RShJ2Vlugu_LIHgLYWM3_cbSJCz7DUcHdgaBoF-KZPhwE/s400/Capture.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Manage users and roles from the MCS portal</td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
The second way is using the services dashboard, using the "Users" tab and clicking "manage roles" for a specific user:<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitJ7KlSs6eeDS5sHJlUKOP3l_UBN_gz4FJhKuGadx1hHYtEHaXUImzXKnqyprk0_7W29_8hwqCvDAet-Lnd1RAOuIM7L_pzqSER2FOyc3-PW2jCQjOdV3Nq14yk2_bkUGYg_sF0mdXAqI/s1600/Capture.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="451" data-original-width="963" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEitJ7KlSs6eeDS5sHJlUKOP3l_UBN_gz4FJhKuGadx1hHYtEHaXUImzXKnqyprk0_7W29_8hwqCvDAet-Lnd1RAOuIM7L_pzqSER2FOyc3-PW2jCQjOdV3Nq14yk2_bkUGYg_sF0mdXAqI/s400/Capture.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Manage roles of a user using the "users tab" from the service dashboard<br />
<br />
<br />
<br />
<div style="text-align: left;">
</div>
</td></tr>
</tbody></table>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><br /></span>
<span style="font-size: small;">But before you can assign the role, you have to go to the user management part of the MCS and create a role in a realm. This is described in the documentation of MCS: "<a href="https://docs.oracle.com/en/cloud/paas/mobile-cloud/mcsua/set-service.html#GUID-AE034938-662D-4679-90F6-8A6510CDFC87" target="_blank">Set Up Mobile Users, Realms and Roles</a>". It also describes naming conventions, for example for roles: </span><br />
<span style="font-size: small;"><i><br /></i></span>
<span style="font-size: small;"><i>"The naming convention for Oracle Cloud custom roles that represent MCS mobile user roles is: <code class="codeph">{serviceName}_MobileEnvironment_{rolename}</code>.
For example, for a role named “APIRole” in the environment with service
name “poeo342ed” the custom role in Oracle Cloud would be <code class="codeph">poeo342ed_MobileEnvironment_APIRole</code>."</i> </span><br />
<span style="font-size: small;"><br /></span>
<span style="font-size: small;">Then you can create a new user account for the tester and assign the newly created role to this user. (S)he then uses account after logging into MCS and changing the default password to test the API from postman, adding the username and password as Basic Authentication to the header of each call.</span><br />
<span style="font-size: small;"><br /></span><span style="font-size: small;">This all works very nicely. But we wanted to assign this role to ourselves. However, the users that were set up as team members did not show up in the MCS User management list of users. </span><br />
<span style="font-size: small;"><br /></span>
So I navigated to my services dashboard again and clicked on the tab "custom roles". Sure enough the role I just created was there, so I assigned my own user to the role and added my username / password to the Postman API call.<br />
The result: "Unauthorized"<br />
<br />
<h4 style="text-align: left;">
Solution</h4>
</div>
Users should not only be assigned to a role to access an API, they should also be part of the realm that is associated with the mobile backend. Unless, of course you use anonymous access, which does not work when you are securing your APIs with roles.<br />
In our example we did not explicitly create a realm, so the mobile backend was associated to the Default Realm. We created the new tester in the default Realm, so this 'role' was automatically assigned to this user. The team members were not added to that realm and therefore did not show up in the list of users of the default realm.<br />
<br />
We added the team members to the Default 'role', which corresponds to the realm in the mobile user management instance and voila! We can access the APIs :)<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigfnXqTuZbDTxUVy0lDWLip4nrLLu-0rH5Dez1J3NBDwMJ7Cv8XhgniHBo-2j4qTyfTTGnoBemgg4ptaAqdp-5BbdBjRdeTUSR8372JNd6iYtoKYu6XHXr5rJ4QeHG9CL9iyqSly3Srtk/s1600/Capture.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="291" data-original-width="1302" height="88" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEigfnXqTuZbDTxUVy0lDWLip4nrLLu-0rH5Dez1J3NBDwMJ7Cv8XhgniHBo-2j4qTyfTTGnoBemgg4ptaAqdp-5BbdBjRdeTUSR8372JNd6iYtoKYu6XHXr5rJ4QeHG9CL9iyqSly3Srtk/s400/Capture.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Role that represents the default realm in the mobile cloud service instance</td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Happy coding!<br />
<br /></div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-68911492016074912142017-07-23T16:47:00.000+02:002017-07-23T16:47:27.350+02:00MCS implementation: How to deploy your custom code with additional libraries<div dir="ltr" style="text-align: left;" trbidi="on">
When implementing APIs that you have defined in Oracle Mobile Cloud Service (MCS), you don't want to reinvent the wheel. That is why it is important to know how to deploy other libraries with your custom code implementation.<br />
<br />
The custom code service that you use when implementing your APIs is backed by the following libraries:<br />
<br />
<ul style="text-align: left;">
<li>Node</li>
<li>Request</li>
<li>Express</li>
<li>Bluebird</li>
<li>Custom code SDK</li>
</ul>
The internal code of MCS uses these libraries. These libraries (with the exception of the '.then' construct from bluebird) are not available for you in your custom code, unless you add them to your custom code zip file. So let's look at an example I ran into during the project, using bluebird.<br />
<br />
<div>
<h3 style="text-align: left;">
Adding bluebird</h3>
<div>
A lot of the Platform APIs that you call from your custom code is executed asynchronously. These methods return a so called 'promise'. A common use case is to chain the calls, using a '<span style="font-family: Courier New, Courier, monospace;">.then</span>' clause. in that case you don't need to add bluebird to your project. However, in our project we needed to join multiple asynchronous calls, not just chain them. </div>
<div>
<br /></div>
<div>
An example: </div>
<div>
<div>
<br /></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">var productIds = req.oracleMobile.database.getAll([table_name], {fields: 'id'}, httpOptions);</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">var orders = req.oracleMobile.database.getAll([another_table_name, {fields: 'id,name, productId'});</span></div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b>var Promise = require('bluebird'</b>);</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Promise.join(productIds, orders).then(</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> function (result) {</span></div>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> //your code here</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> function(error){</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> //your error code here</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"> });</span></div>
<div>
<br /></div>
<div>
Since this uses not just "<span style="font-family: Courier New, Courier, monospace;">.then</span>" but also "<span style="font-family: Courier New, Courier, monospace;">.join</span>" you need to add the required library to your javascript file (<span style="font-family: "courier new", courier, monospace; font-size: x-small;">var Promise = require('bluebird');</span><span style="font-size: x-small;"><span style="font-family: inherit;">)</span></span></div>
<div>
<br /></div>
<div>
According to the documentation you should add bluebird to your zip file, however in our case it worked by just adding the ('require') statement. There is no need to add the bluebird library to the zip.<br />
<br /></div>
<h3 style="text-align: left;">
Adding other libraries</h3>
In our current project a custom implementation is depending on a barcode generator library. You can add this to the custom code zip file that is uploaded to MCS. Note that these additional modules are not shared across custom code modules and you can't install a module that depends on a binary (executable file) on the server.<br />
<br />
To use the modules in your code you have to add it to the dependency list in the <span style="font-family: "courier new" , "courier" , monospace;">package.json</span> file and run <span style="font-family: "courier new" , "courier" , monospace;">npm install</span>.<br />
<br />
<br /><table border="1"><tbody>
<tr><td>Note: when you download the scaffolding code, MCS automatically creates a package.json file. This contains the version "1.0". This results in an error message, because npm uses semantic versioning.<br />
Running npm install on this code will result in the following errors:<br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">npm WARN Invalid version: "1.0"</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">npm WARN sales No description</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">npm WARN sales No repository field.</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">npm WARN sales No README data</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">npm WARN sales No license field.</span><br />
<br />
You can solve this by changing the version to 1.0.0. See for more details: <a href="http://semver.org/">http://semver.org/</a></td></tr>
</tbody></table>
</div>
<br />
In the rest of this blog, I assume you have setup the <a href="http://blog.vennster.nl/2017/07/setup-your-mcs-development-environment.html" target="_blank">MCS custom code testing tools</a>. <br />
In that case you need to take the following steps to deploy the custom code with the additional libraries to MCS:<br />
<br />
<ol style="text-align: left;">
<li>Edit <span style="font-family: Courier New, Courier, monospace;">package.json</span></li>
<li>Run <span style="font-family: Courier New, Courier, monospace;">npm install</span></li>
<li>Test the code locally with <span style="font-family: Courier New, Courier, monospace;">mcs-ccc</span> and mcs-test or postman (or cURL)</li>
<li>Deploy the code with <span style="font-family: Courier New, Courier, monospace;">mcs-deploy</span></li>
</ol>
<br />
<h4 style="text-align: left;">
1. Edit Package.json </h4>
<div>
In our case the package.json looks as follows:</div>
<div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">{</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "name" : "sales",</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "version" : "1.0.0",</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "description" : "The API that facilitates ordering tickets based on a barcode.",</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "main" : "sales.js",</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "dependencies": {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "bwip-js": "1.4.2"</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> },</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "oracleMobile" : {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "dependencies" : {</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "apis" : { },</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> "connectors" : { }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> }</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;">}</span></div>
</div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<h4 style="text-align: left;">
<span style="font-family: inherit;">2. Run npm install</span></h4>
<div>
Navigate to the root directory of your custom code API and install the npm modules you need in your project. In this case the module name is bwip-js. </div>
<div>
<span style="font-size: x-small;"> <span style="font-family: Courier New, Courier, monospace;">npm install bwip-js</span></span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"> npm install</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace; font-size: x-small;"><br /></span></div>
<h4 style="text-align: left;">
3. Test the code locally</h4>
<div>
Make sure the code is working as expected before uploading it to MCS. This is described in a previous <a href="http://blog.vennster.nl/2017/07/testing-packaging-and-deploying-custom.html" target="_blank">post</a>.</div>
<div>
<br /></div>
<h4 style="text-align: left;">
4. Deploy the code to MCS</h4>
<div>
You can run the deployment as usual, from the MCS testing tools: </div>
<div>
<span style="font-family: Courier New, Courier, monospace;">mcs-deploy toolsConfig.json --verbose</span></div>
<div>
<br /></div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-32275666634758870902017-07-17T17:34:00.001+02:002017-07-23T21:01:37.407+02:00Testing, packaging and deploying custom code using MCS custom code test tools<div dir="ltr" style="text-align: left;" trbidi="on">
In a <a href="http://blog.vennster.nl/2017/07/setup-your-mcs-development-environment.html" target="_blank">previous post</a> I have described how to setup your MCS custom code test tools. In this post I will describe how to test, package and deploy your custom code using these tools. You should have installed the MCS custom code tool and updated the toolsConfig.json file with the correct url, mobile backend id and OAuth data.<br />
<br />
<h3 style="text-align: left;">
</h3>
<h3 style="text-align: left;">
Test your code</h3>
Once you have implemented your custom code, you want to test it. Of course you can test it by uploading the implementation into MCS. However, it is much better to test it locally and make sure it works, before you upload it to MCS. Since your custom code probably uses MCS platform APIs, it is convenient to use the mcs-ccc as a local 'container'. Note that when you run the test, it will call the platform APIs in your instance in MCS, so if you insert data in the database, it ends up in the cloud, even though you are running the code locally!<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbdyp7uF_ol5aUGCSt7FAmXVgy11pOJgUVBsI2RVJNn2EfjDyFQIIl1I56WAsnm9C-JBaf8FMNXNUV_vIdyxgOT34k7qdCBKlo1bYjHhVMc_cHca3byzqQ1g2PGQ9XZibdh1AWpnHK968/s1600/testingLocally.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="667" data-original-width="1382" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbdyp7uF_ol5aUGCSt7FAmXVgy11pOJgUVBsI2RVJNn2EfjDyFQIIl1I56WAsnm9C-JBaf8FMNXNUV_vIdyxgOT34k7qdCBKlo1bYjHhVMc_cHca3byzqQ1g2PGQ9XZibdh1AWpnHK968/s400/testingLocally.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Components of the MCS testing tools and communication with MCS instance</td></tr>
</tbody></table>
<br />
You can either run the tests that are defined in the toolsConfig.json or you can run tests in Postman or cUrl.<br />
<br />
When you want to run the test from Postman or cURL, simple point to localhost:4000 instead of the MCS path. Don't forget that the mcs-ccc runs on http, not https.<br />
<br />
The correct values for the port can be found in the output of the console when you start mcs-ccc in verbose mode.<br />
<br />
Instead of running tests from Postman or cURL, you can also run tests that are automatically generated in toolsConfig.json:<br />
<ol style="text-align: left;">
<li>Run <span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">npm install</span></li>
<li>Run <span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">mcs-ccc toolsConfig.json --verbose</span></li>
<li>Open a separate command line</li>
<li>Run <span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">mcs-test <path to toolsConfig.json> <testname> --verbose </span><span style="font-family: inherit;">In this case </span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">mcs-test toolsConfig.json getProductsprices --verbose</span></li>
<li><span style="font-family: inherit;">This returns the response in the command line</span></li>
</ol>
<div>
If you have a template parameter in your call, you have to hard code this in toolsConfig.json and run the test (you can spot these by looking for "PARAMETER").</div>
<div>
<br /></div>
<div>
Advantages of this approach are that the test is automatically generated. The disadvantage is that none of the results are validated. Last but not least, you have to hard code the parameters. For that reason we usually run real system tests in Postman. The testing tool can help the developer in the beginning, to make sure the code that is uploaded will run. It is more for 'smoke-testing' than for real testing of your code.</div>
<h3 style="text-align: left;">
Package and deploy your code</h3>
Once you are ready to package and deploy your code to MCS, you can use <span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">mcs-deploy:</span><br />
<br />
<ol style="text-align: left;">
<li><span style="font-family: inherit;">Navigate to the package</span></li>
<li><span style="font-family: inherit;">Run </span><span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">mcs-deploy toolsConfig.json --verbose</span></li>
<li>Enter the username and password when prompted</li>
</ol>
<div>
You should see the implementation in the MCS API implementation page.</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxAOPM-ADotq95d40TN-EdkJhVlW_487m7N0rqPGnF4JjRRA9OmL0Odk5tB87ad6PQCkKVI5o4K5bSrNXVrH6aBcT-KNUoTEh0EfZdApzdCT0CMzJkhpV3IQJf1yajvL0EXqS9bd4rSPg/s1600/implementation.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="649" data-original-width="1600" height="161" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgxAOPM-ADotq95d40TN-EdkJhVlW_487m7N0rqPGnF4JjRRA9OmL0Odk5tB87ad6PQCkKVI5o4K5bSrNXVrH6aBcT-KNUoTEh0EfZdApzdCT0CMzJkhpV3IQJf1yajvL0EXqS9bd4rSPg/s400/implementation.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">sales 1.0 added as default implementation after running mcs-deploy</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<br />
<br /></div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-19156194060056191372017-07-16T12:49:00.004+02:002017-07-16T12:49:47.663+02:00Set up your MCS (development) environment: database creation policies<div dir="ltr" style="text-align: left;" trbidi="on">
As mentioned in a previous post (<a href="http://blog.vennster.nl/2017/07/setup-your-mcs-development-environment.html" target="_blank">Setup your MCS development environment: MCS custom code test tools</a>, MCS is a cloud native platform that offers several platform APIs. One of these APIs is the database API.<br />
<div>
<br /></div>
<div>
It consists of two parts: </div>
<div>
<ol style="text-align: left;">
<li>Database access. This is used by mobile applications and can only be executed from within custom code</li>
<li>Database management. This allows you to create tables, remove tables etc. </li>
</ol>
</div>
<div>
The first question you might ask is 'why on earth would I want to create tables in MCS, don't we have database cloud service and other sources for that?!?' </div>
<div>
<br /></div>
<div>
Let me start by saying I agree with that. However, in this project we are starting with a simple API and we want to make them available as quickly as possible. The data will move (eventually) to the proper back-end system and in MCS we will use a connector to access this data that will be exposed on the Oracle Service Bus. However, at the moment the system does not contain the data and the Oracle Service Bus is not exposing services for this particular system yet. </div>
<div>
<br /></div>
<div>
To save cost, minimize complexity and maximize time to market, we decided to use the database platform API. </div>
<div>
<br /></div>
<div>
You can create database tables on the fly, using the <code>Database_CreateTablesPolicy</code> environment setting. <span style="font-family: inherit;">This will cause a table </span>or a column to be added or resized when you insert a row using <span style="font-family: inherit;">custom code if it does not exist yet.</span><br />
<span style="font-family: inherit;"><br /></span>
<div>
<span style="font-family: inherit;">According to the <a href="https://docs.oracle.com/en/cloud/paas/mobile-cloud/mcsua/oracle-mobile-cloud-service-environment-policies.html#GUID-283BB031-B85C-4C7B-AA89-B2ED5ACABF66" target="_blank">documentation</a> the following values can be used: </span></div>
<div>
<ul style="text-align: left;">
<li><b>allow</b>: enables calls from custom code that perform implicit operations; </li>
<li><b>explicitOnly</b>: disables implicit calls from custom code;</li>
<li><b>implicitOnly</b>: only implicit creation of database tables using custom code is allowed, the database management api can't be used;</li>
<li><b>none</b>: curtails implicit calls from custom code.</li>
</ul>
<div>
This documentation is a bit unclear so let me elaborate on that:<br />
<br /></div>
<table border="1" padding="5px" text-align="left"><tbody>
<tr><th>Value</th><th>Use API in custom code</th><th>Use implicit calls in custom code </th></tr>
<tr></tr>
<tr><td><span style="font-family: "courier new" , "courier" , monospace;">allow</span></td><td>yes</td><td>yes</td></tr>
<tr><td><span style="font-family: "courier new" , "courier" , monospace;">implicitOnly</span></td><td>no</td><td>yes</td></tr>
<tr><td><span style="font-family: "courier new" , "courier" , monospace;">explicitOnly</span></td><td>yes</td><td>no</td></tr>
<tr><td><span style="font-family: "courier new" , "courier" , monospace;">none</span></td><td>no</td><td>no</td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
<span style="font-family: inherit;"><b>These values are used to control the privileges for custom code, it does not control calling the database management API from outside of MCS (postman, curl etc).</b></span></div>
<br />
There are several disadvantages to this approach:<br />
<ol style="text-align: left;">
<li>You can accidentally end up with multiple columns because of spelling errors ('address' and 'adress' for example);</li>
<li>When unit testing custom code with 'faulty' data, instead of failing with the error you would get into your production environment (which is recommended by Oracle, to switch it off in production) you create new columns and the test fails with a different error (if it fails at all);</li>
<li>We use the environment that we are working as a production environment. </li>
</ol>
<div>
We decided to use "<span style="font-family: Courier New, Courier, monospace;">explicitOnly</span>" and use the REST APIs to create, update and remove tables with Postman. However when I used one of the APIs I got the following response:</div>
<div>
<br /></div>
<br />
<div>
<span style="color: red;"><b>{</b></span></div>
<div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.1",</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "status": 403,</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "title": "Forbidden",</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "detail": "403 - Forbidden",</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "o:ecid": "005L4J3QBg63j4C_nDWByZ0000x^0000yX, 0:3",</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "o:errorCode": "MOBILE-15229",</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b> "o:errorPath": "/mobile/system/databaseManagement/tables"</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace; font-size: x-small;"><b>}</b></span></div>
</div>
</div>
<div>
<br /></div>
<div>
<span style="font-family: inherit;">When creating a database table from outside the custom code (using the REST API and postman for example), you </span><span style="font-family: inherit;">need to call it with a user that has the role </span><span style="font-family: "courier new", courier, monospace;">Mobile_DbMgmt. </span>Unfortunately, there is no easy way to check your role from inside MCS, as can be seen in this picture<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0rW6p1jTf5rghrp9mzftQiZOOynG8fFeKu2oduSxnMCnRcB6HLVLZWn95DS_rbImOtXNL1MTosOB1myU9j1-bUC7r5C7syMF-cSQGx6ZApivLSuGWcxnaKFfRqfYsztUrzK08NnaDhxQ/s1600/navigation.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="769" data-original-width="1600" height="191" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi0rW6p1jTf5rghrp9mzftQiZOOynG8fFeKu2oduSxnMCnRcB6HLVLZWn95DS_rbImOtXNL1MTosOB1myU9j1-bUC7r5C7syMF-cSQGx6ZApivLSuGWcxnaKFfRqfYsztUrzK08NnaDhxQ/s400/navigation.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="font-size: 12.8px;">No easy navigation to inspect or change your role from within MCS</td></tr>
</tbody></table>
So, I opened a new tab and navigated to cloud.oracle.com and signed in again. This brought me to my service dashboard, and offers the opportunity to manage users, using the "users" button in the upper right hand corner.<br />
Click users and find yourself. Check your roles and add <span style="font-family: Courier New, Courier, monospace;"><b>[environment name] Mobile Database management</b></span> to the roles.<br />
<br />
Now I was able to create the table 😊.<br />
<span style="font-family: inherit;"><br /></span>
<span style="font-family: inherit;"><b>NB</b>: According to the documentation the default value is '<span style="font-family: Courier New, Courier, monospace;">allow</span>'. In our instance the value was set to '</span><span style="font-family: Courier New, Courier, monospace;">explicitOnly</span><span style="font-family: inherit;">', so make sure you check the value when you use the database platform API. </span><br />
<br /></div>
<div>
<ol style="text-align: left;">
<li>Login to MCS</li>
<li>Click on "Administration"</li>
<li>Scroll to the bottom of the page</li>
<li>Click Export and save the policy file.</li>
<li>Edit the policy (if needed)</li>
<li>Upload policies.properties</li>
</ol>
</div>
<div>
<span style="font-family: inherit;">The setting is applied instantly.</span></div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-67453540144052159062017-07-13T23:13:00.000+02:002017-07-17T18:05:34.435+02:00Setup your MCS development environment: MCS custom code test tools<div dir="ltr" style="text-align: left;" trbidi="on">
Oracle Mobile Cloud Service is a so called 'cloud native' product in the Oracle PaaS offering: it runs in the Oracle Public Cloud and there is no on premise variant in the Oracle Fusion Middleware stack.<br />
<br />
In our current MCS project we have set up a number of things to make sure that we can achieve the same quality in our software development lifecycle (sdlc) as we have in our 'traditional' projects. One of the measures is the ability to run unit tests locally before deploying the code.<br />
<br />
MCS is a cloud service that is based on node.js. It offers a number of platform APIs that you can use when creating custom APIs for mobile developers. The figure below shows these platform APIs: storage APIs to store files, Database APIs to store relational data, notifications etc. When you write a custom API, you use the platform APIs and you call connectors in the implementation.<br />
<br />
When you use a tool like Netbeans (or any other javscript tool), these platform APIs are not available, which makes it hard to test your code without installing it on MCS. To solve this problem, MCS offers <b><i>MCS custom code test tools</i></b>.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img alt="Description of intro-arch.png follows" class="imagecenter" src="http://docs.oracle.com/en/cloud/paas/mobile-cloud/mcsua/img/intro-arch.png" longdesc="img_text/intro-arch.html" style="margin-left: auto; margin-right: auto;" title="Description of intro-arch.png follows" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Architecture of MCS (from the documentation)</td></tr>
</tbody></table>
<br />
<h3 style="text-align: left;">
MCS custom code test tools</h3>
<div>
It took me a while to discover the MCS testing tools, because I am a so-called 'service developer'. The testing tools are located in the SDK which is targeted at the role 'mobile app developer' who use, not build, the custom APIs. (Hint @Oracle: please make the MCS tools available in the implementation page for the API). </div>
<div>
<br /></div>
<div>
<b>Prequisites</b>: </div>
<div>
<ul style="text-align: left;">
<li>local version of node.js (6.10) and <a href="https://docs.npmjs.com/getting-started/what-is-npm" target="_blank">npm </a></li>
<li>An account on Oracle Mobile Cloud Service (MCS) with role 'developer'</li>
<li>An API scaffolding to test the setup</li>
<li>A development tool of choice (in this case Netbeans)</li>
</ul>
</div>
<div>
<br /></div>
<div>
The following steps need to be taken to go through the entire lifecycle: </div>
<div>
<ol style="text-align: left;">
<li>Download the MCS custom code test tools</li>
<li>Install the MCS custom code test tool on your machine using npm</li>
<li>Setup your mobile backend for testing</li>
<li>Set the custom API up for testing</li>
<li>Run it locally (yay!! 😊) with the MCS custom code test tools</li>
</ol>
<h4 style="text-align: left;">
Download the MCS custom code test tool</h4>
</div>
<div>
1. Navigate to the MCS <a href="http://www.oracle.com/technetwork/topics/cloud/downloads/mobile-cloud-service-3636470.html" target="_blank">download </a>page.<br />
<br />
<b><span style="color: red;">NB: don't use the downloal link on the applications page, it will bring you to a download page, without the mcs-tools folder!!</span></b></div>
<div>
<br /></div>
<div>
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjySfH6F60y_Cgev5F-rvXYrq_HpcJCDz8NuXg99kf6kv3YxkRDX0zEFfVE9lFnJ-Aw4NXosVrQqHVuGn1ZhII215F6eJ7thIucycFaxDueckB4VRGnnBzPj4NMOKNprV4gqpU7qBmkzgg/s1600/MCS-SDK.PNG" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="182" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjySfH6F60y_Cgev5F-rvXYrq_HpcJCDz8NuXg99kf6kv3YxkRDX0zEFfVE9lFnJ-Aw4NXosVrQqHVuGn1ZhII215F6eJ7thIucycFaxDueckB4VRGnnBzPj4NMOKNprV4gqpU7qBmkzgg/s400/MCS-SDK.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><b><span style="color: red;">Don't click on this link!!</span></b></td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
2. Select any SDK (every SDK contains MCS custom code test tools), unfortunately there is no separate download for service developers and download it (hint @Oracle)</div>
<div>
3. Extract the file to a location of choice. Navigate to the mcs-tools folder and extract this folder into the location of choice. Note that the mcs-tools folder contains the mcs-tools folder. This is the folder you need. </div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-GZ6Wl4JmSkKuGhS_0YW7yP4NJtHAI3WMpqeq1Sp85Zo5gknQFwzzOLoWqmMwIrjrN_zNVp6KV91G66HsTcxoK1FE_JoksPX6sSpAYxQQnmYrbt_tFeNF-zWWlVYa_MusXZ3FO9DoqnA/s1600/download.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi-GZ6Wl4JmSkKuGhS_0YW7yP4NJtHAI3WMpqeq1Sp85Zo5gknQFwzzOLoWqmMwIrjrN_zNVp6KV91G66HsTcxoK1FE_JoksPX6sSpAYxQQnmYrbt_tFeNF-zWWlVYa_MusXZ3FO9DoqnA/s400/download.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">SDK files</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbFyiBblCgMT8klbFxwB9VWfIbiWnWTMFNSJI9wKkitPdVpWF1NSDOZ5LPpRwEQgS7JVq_mVhUllfhApMx4tsA-PMIFQpWuFc9kp46EuSRGmsAwylXNACY9ed0sELXAFYDd7dxqAxSnR8/s1600/mcs-tools.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="78" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbFyiBblCgMT8klbFxwB9VWfIbiWnWTMFNSJI9wKkitPdVpWF1NSDOZ5LPpRwEQgS7JVq_mVhUllfhApMx4tsA-PMIFQpWuFc9kp46EuSRGmsAwylXNACY9ed0sELXAFYDd7dxqAxSnR8/s400/mcs-tools.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">mcs-tools directory containing mcs-tools directory</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
</h4>
<h4 style="text-align: left;">
Install the MCS testing tool</h4>
<div>
<ol style="text-align: left;">
<li>open a terminal session and navigate to the deepest mcs-directory: mcs-tools</li>
<li>run npm to install the tool on your machine</li>
<li>test the installation, it my case it returns 17.2.5</li>
</ol>
</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">cd {sdk path}/mcs-tools/mcs-tools</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">npm install -g</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">mcs-test --version</span></div>
<div>
<br /></div>
<h4 style="text-align: left;">
<span style="font-family: inherit;">Setup your mobile backend for testing</span></h4>
<div>
<ol style="text-align: left;">
<li><span style="font-family: inherit;">Create a new API that will act as a proxy for your local tests by adding the OracleMobileAPI.raml in the "Create API" dialog. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCiyr8GHoly-Epie4FNxaGZqMFCd3WQgoxpgzad8yDBWUc2tNcHCJgZURL5tGpshRkXk3WgM5shspU3obiDDmKBuG_9Ftw7VUtk6H9pa5SfGVtYpVq5KcXMvgeks1tRCTXFjSvD953lU4/s1600/MobileAPI.PNG" imageanchor="1"><img border="0" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCiyr8GHoly-Epie4FNxaGZqMFCd3WQgoxpgzad8yDBWUc2tNcHCJgZURL5tGpshRkXk3WgM5shspU3obiDDmKBuG_9Ftw7VUtk6H9pa5SfGVtYpVq5KcXMvgeks1tRCTXFjSvD953lU4/s320/MobileAPI.PNG" width="320" /></a></span></li>
<li><span style="font-family: inherit;">Add the implementation by uploading the "OracleMobileAPIImpl.zip" to the implementation of the API.</span></li>
<li><span style="font-family: inherit;"> </span> <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDZKmDgDAV4cChe8PqDCarEJ0_G4w_BnyR1v9dkl18-pB0ZAdB5sjkQT6osVkOIGhhl0oRByeXIx8YPfaVctY4Awmx-qZe2eMUKkA5dh5c9VKIUJHPfQmbQX0A0jY4tJoPUbunHwkPKWU/s1600/mobileAPIImplementation.PNG" imageanchor="1" style="font-family: inherit;"><img border="0" height="130" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDZKmDgDAV4cChe8PqDCarEJ0_G4w_BnyR1v9dkl18-pB0ZAdB5sjkQT6osVkOIGhhl0oRByeXIx8YPfaVctY4Awmx-qZe2eMUKkA5dh5c9VKIUJHPfQmbQX0A0jY4tJoPUbunHwkPKWU/s400/mobileAPIImplementation.PNG" width="400" /></a></li>
<li><span style="font-family: inherit;">Switch off "Login required" in the security tab. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHHwIOyksF8vx5Jjvb2CGJmFJ4FToolPX6UNLNaIPUOw1Gh8dkAwz9ORiqyVjpexVITM4vWCSepdiSqf1BZz0Dr89qCENIOoTQGnQTtjkvQ3Hnq-_nfVyuLuXeWhFeaIXNIYL_Eeod6Eo/s1600/noLogin.PNG" imageanchor="1"><img border="0" height="145" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHHwIOyksF8vx5Jjvb2CGJmFJ4FToolPX6UNLNaIPUOw1Gh8dkAwz9ORiqyVjpexVITM4vWCSepdiSqf1BZz0Dr89qCENIOoTQGnQTtjkvQ3Hnq-_nfVyuLuXeWhFeaIXNIYL_Eeod6Eo/s320/noLogin.PNG" width="320" /></a></span></li>
<li><span style="font-family: inherit;">Add the API to the mobile backend. <a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifl2RBDdvr391UL-Pz62cg0oaPp94Hc8y1L4iUk-CirARDHeg2S9Nqnx3mG7NpX8L77r7Y9T1OvTdbu-qlh-go0eXvNgSwy_hzF92A5-aLdzZoPe7e32ipvZ5eeNBvqi9e54bpQw0pCXw/s1600/addToBackEnd.PNG" imageanchor="1"><img border="0" height="73" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEifl2RBDdvr391UL-Pz62cg0oaPp94Hc8y1L4iUk-CirARDHeg2S9Nqnx3mG7NpX8L77r7Y9T1OvTdbu-qlh-go0eXvNgSwy_hzF92A5-aLdzZoPe7e32ipvZ5eeNBvqi9e54bpQw0pCXw/s400/addToBackEnd.PNG" width="400" /></a></span></li>
</ol>
<h4 style="text-align: left;">
Setup your custom API for local testing</h4>
<div>
<ol style="text-align: left;">
<li>navigate to the root folder of your local API implementation (or the scaffolding if you did not create an implementation yet)</li>
<li><span style="font-family: inherit;">run </span><span style="font-family: "courier new" , "courier" , monospace;">npm install</span></li>
<li>update the 'toolsConfig.json' file and enter the mobile backend id, the anonymous key and the OAuth data that are used to deploy to MCS. They can be found in the mobile backend settings page. For obvious reasons, I don't show the details here 😉</li>
</ol>
</div>
<h4 style="text-align: left;">
<span style="font-family: inherit;">Run it locally</span></h4>
</div>
<div>
<span style="font-family: inherit;">1. Open a terminal</span></div>
<div>
2. Run the mcs-ccc with the correction options (you can also use --debug to debug in Chrome)</div>
<div>
<br /></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;">mcs-ccc toolsConfig.json --verbose</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span>
<span style="font-family: inherit;">The result is:</span></div>
<div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">C:\Users\ldikmans\Documents\api-straat\product\productapi> mcs-ccc .\toolsConfig.json</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Warning: Configuration property "proxy" is undefined</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">To display help and examples associated with warnings, use the --verbose option</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">Ping OracleMobileAPI to verify that OracleMobileAPI-uri and authorization are correct.</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">OracleMobileAPI ping succeeded!</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace; font-size: x-small;">The Node server is listening at port 4000</span></div>
</div>
<div>
<br /></div>
<div>
The downside of this approach is that you have added a 'foreign' API to your mobile backend. You can handle this in two ways, depending on how many environments you have:</div>
<div>
<ol style="text-align: left;">
<li>Remove the OracleMobileAPI from the mobile backend as soon as you publish it</li>
<li>Remove the OracleMobileAPI from the mobile backend in your test or production instance. </li>
</ol>
</div>
<div>
<br /></div>
<div>
In the next blog I will describe how you can test, package and install your custom code into MCS, using 'mcs-tools'. </div>
<div>
<br /></div>
<div>
Happy coding 😊</div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><br /></span></div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-22780404804167669842016-12-02T16:26:00.000+01:002016-12-02T16:26:05.342+01:00Securing Cross-Site Requests to MCS APIs<div dir="ltr" style="text-align: left;" trbidi="on">
When your Oracle Mobile Cloud Service APIs are being accessed by a remote server, it is important you manage cross-origin resource sharing (CORS)
We ran into this issue when we were building the solution for the Oracle cloud day. The MCS APIs were accessed by a Web Application that was hosted on a different domain, not on our Oracle PaaS domain.
When calling an API from the application, we received the error:<br />
<br />
<span style="color: red; font-family: Courier New, Courier, monospace;"><b>XMLHttpRequest cannot load: [request url]. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin [origin domain] is therefore not allowed access. The response had HTTP status 401.</b></span><br />
<br />
You can either disallow CORS altogether, or whitelist specific sites. This is done by setting a property in policies.properties: <span style="font-family: Courier New, Courier, monospace;">Security_AllowOrigin.</span><br />
<br />
An example of the property can be seen below:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;"> *.*.Security_AllowOrigin=http://myapp.eproseed.com</span><br />
<br />
This means that requests coming from myapp.eproseed.com from port 80 are allowed.<br />
<br />
More information can be found in the <a href="http://docs.oracle.com/en/cloud/paas/mobile-cloud/mcsua/authentication-mcs.html#GUID-B5445574-1EEB-4431-9599-CA6215ACC96F__GUID-D08CC35F-9139-453F-92EE-6BD127414DD0" target="_blank">Using Oracle Mobile Cloud Service, Part II: Setting up Mobile Apps, Chapter 5</a>. This chapter explains in detail the pattern matching that is applicable.<br />
<br />
To summarize:<br />
<br />
1. Login to MCS<br />
2. Click on "Administration"<br />
3. Scroll to the bottom of the page<br />
4. Download policies.properties<br />
5. Edit or add the property<br />
6. Upload policies.properties.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH1om9hTkyFCYz1ylBaN93qEkYr59Jv46rg6OR1CoLCnM0shMmqQbQBM7YPtWIRRYvuj4AEEAOqmUCdsIWTFuE5jYxRH-BC4FphxwcFUomi2roD1WBST-mVf3aIGKUlwrLmFwk3Q5NEYc/s1600/Screen+Shot+2016-12-02+at+16.18.51.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="195" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgH1om9hTkyFCYz1ylBaN93qEkYr59Jv46rg6OR1CoLCnM0shMmqQbQBM7YPtWIRRYvuj4AEEAOqmUCdsIWTFuE5jYxRH-BC4FphxwcFUomi2roD1WBST-mVf3aIGKUlwrLmFwk3Q5NEYc/s400/Screen+Shot+2016-12-02+at+16.18.51.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Administration page in MCS</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
The setting is applied instantly.
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-54648062097927462942016-11-19T14:46:00.000+01:002016-11-22T19:18:55.354+01:00Editing Application Roles in Oracle Process Cloud Service<div dir="ltr" style="text-align: left;" trbidi="on">
The other day I was working on my demo of Oracle Process Cloud Service (PCS) for <a href="http://apps16.ukoug.org/default.asp?p=15232&dlgact=shwprs&prs_prsid=12420&day_dayid=107" target="_blank">UKOUG Apps 2016</a>. After creating the application, I wanted to start working on the process. My use case fits an out of the box pattern nicely, so I started with "Form Approval with Integration Pattern" and PCS created a default process for me; with two swimlanes and a number of activities. The resulting process is shown below.<br />
<div>
<span id="goog_1855696741"></span><span id="goog_1855696742"></span><br />
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnLa9I0n9fXKC3z9yOMmcgfTOaisHKDLccdGiR4Gro-2TGxV1ZUntE9FKv0s2aKC4h2OF5zfJgUtr3LRfX2tHzR_-YDPcAuq79D2t3JzACurSH4-UVnWiRTjnJ3EnRt0LuEN0AVdAzJdE/s1600/-1728225582.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgnLa9I0n9fXKC3z9yOMmcgfTOaisHKDLccdGiR4Gro-2TGxV1ZUntE9FKv0s2aKC4h2OF5zfJgUtr3LRfX2tHzR_-YDPcAuq79D2t3JzACurSH4-UVnWiRTjnJ3EnRt0LuEN0AVdAzJdE/s400/-1728225582.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Process created based on "Form Approval with Integration Pattern"</td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Every PCS application is provisioned with three standard roles:<br />
<ol style="text-align: left;">
<li>Process Owner. Users with this role have access to process activity history, can take actions, alter the process flow etc. Process owners typically manage deployed business processes and use metric analysis tools such as dashboards to monitor the business process. </li>
<li>Process Reviewer. This role gives access to process activity, but process reviewers can not take actions on tasks or alter tasks flows. Process reviewers are not participating but typically responsible for reporting on current process instance status. </li>
<li>Analytics Viewer. assigned this role can create and view business analytics dashboards associated with the specified application.
</li>
</ol>
<div>
In this example, I don't want to use these global application roles, I want two other roles:</div>
</div>
</div>
<div>
<ol style="text-align: left;">
<li>Expense Submitter. An employee that submits an expense because of traveling or other reasons</li>
<li>Expense Approver. The manager of the employee that approves the expense items on the expense report.</li>
</ol>
</div>
<div>
You can edit the swimlane by clicking on the pencil icon next to the swimlane and select a role. </div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9K6q9PL8qA71-LWTTmdsNDGit-oqjsnkjT6-7rGEwptB1XnU77TCK9UIvLgNYJFtFTw4Be_lYXvTCW9KMjWFWp4-DGjjucsf8MGaC78B2LDimVi3QkZWfv-5G_BWSYC_pgX_TyuiRugw/s1600/Screen+Shot+2016-11-19+at+13.25.46.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="255" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj9K6q9PL8qA71-LWTTmdsNDGit-oqjsnkjT6-7rGEwptB1XnU77TCK9UIvLgNYJFtFTw4Be_lYXvTCW9KMjWFWp4-DGjjucsf8MGaC78B2LDimVi3QkZWfv-5G_BWSYC_pgX_TyuiRugw/s400/Screen+Shot+2016-11-19+at+13.25.46.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Assigning an application role to a swimlane</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
</div>
<br />
<div>
<span style="background-color: white; color: #222222; font-family: "helvetica neue" , "neue helvetica" , "arial" , sans-serif; font-size: 14px;"><br /></span></div>
<div>
<span style="background-color: white; color: #222222; font-family: "helvetica neue" , "neue helvetica" , "arial" , sans-serif; font-size: 14px;"><br /></span></div>
<br />
<br />
<br />
<div>
<br />
<br />
<br />
<br />
<br />
<br />
<br />
I did not see the role I was looking for in the list, but that is not a problem: I can add an Application Role to the list by clicking the "+" icon.<br />
<br />
So far so good. I added a role "Expenser" and assigned the first swimlane to it. Then I did the same for the second swimlane: I edited the swimlane and added a new role "Expense Approver".<br />
<br />
Unfortunately, I made a mistake....<br />
<br />
<h3>
Editing the role</h3>
<div>
I wanted to call the first swimlane/role "Expense Submitter", remember? I accidentally named it "Expenser". I want to change this name, because I don't like it.</div>
<div>
<br /></div>
<div>
My first attempt is in the current screen. I have the pencil next to the swimlane, so probably I can edit the role here, right? Wrong.</div>
<div>
It will bring me back to assigning a role to a swimlane. I can assign it to a different role or a new role. But not edit it. </div>
<div>
So let's look at another option, there is another place to manage roles, on an application level.</div>
<div>
<br /></div>
<div>
Click on the tab "Application Home". This will bring you back to the Application Home. When you click on the "Organisation" link, you will get a pop-up that allows you to delete or add roles. However, <b><span style="color: red;">you can't edit roles.</span> </b></div>
<div>
<b><br /></b></div>
<div>
Because I really wanted a new name, I deleted the role and added a new one.</div>
<div>
<br /></div>
<table border="1px solid black">
<tbody>
<tr><td><b><i>Remember, adding a role will not only impact the swimlane, but also adds an application role for the application. This role will be available for all processes in this application.</i></b></td></tr>
</tbody></table>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihwrJCrVeKXrQY3okbvpoCU5NTB921ePFuD_cGT34O1Cd9MTiCj7dN6mbrjpO-fx6m8lb4y8J_lUNwMhwnr_O3L_FjoLhC788UyBacShxDv38fVE6yTD1qO6VEjGwfeO3l5iqJD0EbNuc/s1600/Screen+Shot+2016-11-19+at+13.49.14.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEihwrJCrVeKXrQY3okbvpoCU5NTB921ePFuD_cGT34O1Cd9MTiCj7dN6mbrjpO-fx6m8lb4y8J_lUNwMhwnr_O3L_FjoLhC788UyBacShxDv38fVE6yTD1qO6VEjGwfeO3l5iqJD0EbNuc/s400/Screen+Shot+2016-11-19+at+13.49.14.png" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Application Home with Dialog to add and remove Application Roles</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
Of course this makes you wonder what happened with the swimlane that was using the role we just deleted?</div>
<div>
<br /></div>
<div>
Let's see:</div>
<div>
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnYYGJEh4fAn_c31KE-VyrFASaN02rLCArX-h6T1syVP0K-fWyrC26BQ4oVWUsZInck_JV0aMfI9gA6_nof5-cD5r_90rTicdZRTzIrVQVJb-4aVZmeRMlMyAWjLQTpG104RbeJPnNyfI/s1600/Screen+Shot+2016-11-19+at+13.51.24.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjnYYGJEh4fAn_c31KE-VyrFASaN02rLCArX-h6T1syVP0K-fWyrC26BQ4oVWUsZInck_JV0aMfI9gA6_nof5-cD5r_90rTicdZRTzIrVQVJb-4aVZmeRMlMyAWjLQTpG104RbeJPnNyfI/s320/Screen+Shot+2016-11-19+at+13.51.24.png" width="282" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Unassigned role after deleting a role from the application</td></tr>
</tbody></table>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
<br /></div>
<div>
It results in a swimlane with a 'Unassigned role'. So I assigned the newly created role and continued with implementing the process. </div>
<div>
<br /></div>
<h3>
Conclusion</h3>
<div>
From a functional perspective, the ability to create a process based on a pattern is very powerful. The responsiveness of the process composer is very good. It is a pleasure to work with it, it feels like a modern application. However from a user experience perspective, I see plenty of room for improvement: </div>
<div>
<ol>
<li>Navigation</li>
<ul>
<li>Buttons versus links. Why is 'Organization' a link, not a button at the right hand side of the Application Home? Why is closing the application implemented with a link and not a button? There are multiple levels of navigation, and it is not always clear why which pattern is used for what level.</li>
<li>Moving from the Workspace to the Process Composer. It is unclear to me how to get back to the workspace once you have entered the process composer, apart from saving the link as a favorite in your browser.</li>
</ul>
<li>Internationalization</li>
<ul>
<li>Some concepts are translated, some are not. </li>
<li>Consistency. It seems that in the Dutch version, a project role is edited (see illustration), in the English version the dialog is called "edit Application roles" (the correct concept) . </li>
</ul>
<li>Concepts. </li>
<ul>
<li>The name of the Swimlane is the same as the role you assign to it. The role is defined on an Application Level, not a process level. This is not clear from the way it is presented to the user and will only occur to the process developer, once (s)he will develop more than one process</li>
<li>It is not possible to edit the name of the role. You have to delete it and then add a new role. This will result in swimlanes with unassigned roles in existing processes. </li>
<li>It is unclear for the process developer what a role entails, the pop-up window does not show where the role is used or what permissions are associated with it</li>
<li>By default the submitter of a form is defined as the process owner. In most cases this will not be the case: the receiver of the form is typically the process owner, who will approve or deny the request and has the ability to change the process etc.</li>
</ul>
</ol>
<div>
This is not an extensive list, but just the issues I ran into while trying to change the name of a process role after having created a process based on a pattern. </div>
<div>
<br /></div>
From a functionality perspective PCS is becoming more and more powerful. However, it is very important to keep the User Experience that comes with the functionality consistent within itself and with the other Oracle products as well. Including the Oracle Applications. Because for users, the difference between PaaS and SaaS is inconsequential, they just use the tools. In the end, to users it does not matter whether Oracle calls these tools a 'Platform' or 'Software'. What matters is that they are productive and that the tools are easy to understand. </div>
<div>
<br /></div>
<div>
I think it is time that Oracle repositions the <a href="http://www.oracle.com/webfolder/ux/applications/index.html" target="_blank">Oracle Usable Apps</a> group to a higher level to include the PaaS products. And please, as a first recommendation from a UX perspecive, let me edit roles 🙏</div>
<div>
<br /></div>
<div>
<br /></div>
</div>
</div>
Lonneke Dikmanshttp://www.blogger.com/profile/00409831781155969611noreply@blogger.com0tag:blogger.com,1999:blog-1766203392912336249.post-33292666842358596362015-05-05T16:54:00.002+02:002015-05-05T16:55:47.813+02:00Virtual Technology Summit: Hands-On Learning With Oracle and Community ExpertsThe Oracle Technology Network (OTN) is organizing another Virtual Technology Summit this May. The summit includes Database, Java, Middleware, and OS/Virtualization/Hardware content. The VTS will be offered on May 5th, May 12th and May 19th. Lonneke and I will present the following session on reuse in Oracle SOA Suite 12c:<br />
<br />
<br />
<blockquote class="tr_bq">
Most people in IT agree: you want to reuse code, rather than type the same thing twice. Choosing the right type of reuse can greatly speed up your development, decrease maintenance efforts, and reduce the number of errors by eliminating similar code.<br />
<br />
Of course you can copy something, and reuse it that way. However, this is hard to do, especially if somebody changes the original code. In SOA Suite 12c there are several ways to reuse code, implement patterns and quickly start your project. These options vary from project skeletons using Maven poms to composite templates and creating services. In this presentation we will explain the difference between a pattern, a library and a (micro)service and illustrate this with features from the SOA Suite 12c: maven, templates (BPEL and OSB), BPEL subprocesses, and services. The features will be explained using real-life examples. We will also discuss common pitfalls we have encountered.<br />
<br />
At the end of this session attendees will be familiar with the facilities that SOA Suite offers to create consistent quality in projects, and will be better equipped to choose the appropriate method (library, pattern or service) to use in any situation.</blockquote>
View the full agenda <a href="https://community.oracle.com/docs/DOC-911884">here</a>, enjoy!Ronald van Luttikhuizenhttp://www.blogger.com/profile/16349079496824277926noreply@blogger.com0Nijmegen, Nederland51.8125626 5.837226399999963251.6555996 5.5145028999999628 51.9695256 6.1599498999999636tag:blogger.com,1999:blog-1766203392912336249.post-51113140704544847592015-04-20T09:04:00.000+02:002015-05-06T09:05:10.631+02:00Creating the platform of the future with Oracle Fusion Middleware 12c The article "Creating the platform of the future with Oracle Fusion Middleware 12c" written by Antonis Antoniou and myself is published in UKOUG's <a href="http://viewer.zmags.com/publication/cdb0833d#/cdb0833d/53">Oracle Scene Issue 56</a>. <br />
<br /><br />
The article shows how Oracle Fusion Middleware 12c offers one complete, modern, open and integrated stack that allows you to create a future-proof platform. To highlight the features of the stack we have used the example of handling lost-luggage by an airline. Based on this use case, the article explains how Oracle Fusion Middleware provides mobile and web access from any device based on user and customer experience best practices. How it enables applications to be responsive and to create valuable insights by incorporating big and fast data capabilities; and gives you control over both structured as well as unstructured knowledge-driven processes. It then discusses its best-in-class integration capabilities, both between the products in the Fusion Middleware stack, as well as with other applications and data either running in the Cloud or on-premise. Ronald van Luttikhuizenhttp://www.blogger.com/profile/16349079496824277926noreply@blogger.com0Nijmegen, Nederland51.8125626 5.837226399999963251.6555996 5.5145028999999628 51.9695256 6.1599498999999636tag:blogger.com,1999:blog-1766203392912336249.post-14776421063350122852014-08-13T09:01:00.000+02:002014-08-13T09:01:53.200+02:00Create Service Bus Customization File using WLSTFor one of our Oracle Fusion Middleware projects we had the requirement that the IT Ops activities should be scripted as much as possible. These activities included things like packaging, deploying, and automated testing of Service Bus projects, SOA Composites, and BPM processes. One of the more challenging tasks to script was to create and extract the runtime configuration of services deployed on Oracle Service Bus 11g using customization files. There seems to be no WLST feature readily available for this purpose. Based on some resources that all contained part of the solution, we were able to construct a WLST script for this purpose which you can find in this blog.<br />
<br />
This blog briefly explains the use of customization files, how to create a customization file using the Service Bus Console, includes the WLST script to execute this task, and provides a brief conclusion.<br />
<br />
<h4>
Customization Files</h4>
Customization files are XML files that contain the configuration of Service Bus resources and projects. Examples of such configurations are Service URIs, JCA settings, Retry Settings, and so on. Customization files provide a convenient way to apply environment-specific configuration during deployment. You can both apply, as well as create and extract the runtime configuration of Service Bus resources and projects into customization files using the Service Bus Console.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk5oNLZyXKB7XVSRu-UyCiXrmpxuWHLGii3vRrlS4eVNeb7_BGwGw60lZ49sKVlo4sVN1rEbJEajc8EuXXyOgYkxtTKzpt6g6CkbVlRqFpBeCkiqE3xFlcmnG7Tc77gyXsOkNfKXkXeCg/s1600/WLST_OSB_Customization_File_Blog.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjk5oNLZyXKB7XVSRu-UyCiXrmpxuWHLGii3vRrlS4eVNeb7_BGwGw60lZ49sKVlo4sVN1rEbJEajc8EuXXyOgYkxtTKzpt6g6CkbVlRqFpBeCkiqE3xFlcmnG7Tc77gyXsOkNfKXkXeCg/s1600/WLST_OSB_Customization_File_Blog.png" height="176" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Creating customization file using the Service Bus Console</td></tr>
</tbody></table>
<br />
Read more about customization files in the <a href="http://docs.oracle.com/cd/E23943_01/admin.1111/e15867/customization.htm">Oracle Fusion Middleware Administrator's Guide for Oracle Service Bus</a>.<br />
<br />
<h4>
WLST Script</h4>
Based on the following resources a WLST script can be created to export an OSB project including its customization file from a runtime environment:<br />
<br />
<ul>
<li><a href="https://github.com/biemond/soa_tools/tree/master/maven_osb_ps5">OSB Maven and Ant scripts from Edwin Biemond</a> </li>
<li><a href="https://community.oracle.com/thread/966771">OTN Forum Post</a></li>
</ul>
<br />
The WLST script is as follows:<br />
<br />
<span style="font-family: Courier New, Courier, monospace;">from java.io import FileOutputStream</span><br />
<span style="font-family: Courier New, Courier, monospace;">from java.util import Collections</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">from com.bea.wli.config import Ref</span><br />
<span style="font-family: Courier New, Courier, monospace;">from com.bea.wli.config.mbeans import ConfigMBean </span><br />
<span style="font-family: Courier New, Courier, monospace;">from com.bea.wli.sb.util import EnvValueTypes</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">import sys</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">#==================================================</span><br />
<span style="font-family: Courier New, Courier, monospace;"># Utility function to export project and cust file</span><br />
<span style="font-family: Courier New, Courier, monospace;">#==================================================</span><br />
<span style="font-family: Courier New, Courier, monospace;">def exportProject():</span><br />
<span style="font-family: Courier New, Courier, monospace;"> try:</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if projectName == "None":</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "No project specified, exiting deployment"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> exit(exitcode=-1)</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> if customizationFile == "None":</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "No customization file specified, exiting"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> exit(exitcode=-1)</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> ALSBConfigurationMBean = findService("ALSBConfiguration", "com.bea.wli.sb.management.configuration.ALSBConfigurationMBean")</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "ALSBConfigurationMBean found"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> configMBean = JMX.newMBeanProxy(mbs, ObjectName.getInstance("com.bea:Name=Config.XBus Kernel,Type=com.bea.wli.config.mbeans.ConfigMBean"), ConfigMBean)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "ConfigMBean found"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> # Get reference to OSB project </span><br />
<span style="font-family: Courier New, Courier, monospace;"> ref = Ref.makeProjectRef(projectName);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> collection = Collections.singleton(ref)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> # Export OSB project JAR </span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "Export JAR for OSB project:", projectName</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> theBytes = ALSBConfigurationMBean.exportProjects(collection, passphrase)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> aFile = File(exportJar)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> out = FileOutputStream(aFile)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> out.write(theBytes)</span><br />
<span style="font-family: Courier New, Courier, monospace;"> out.close()</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "Project " + projectName + " exported"</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;"> # Export OSB customization file</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "Export customization file for:", projectName</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> theBytes = configMBean.createCustomizationFile(collection, EnvValueTypes.ENV_VALUE_TYPES);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> out = FileOutputStream(customizationFile);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> out.write(theBytes);</span><br />
<span style="font-family: Courier New, Courier, monospace;"> out.close();</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "Cust file for " + projectName + " exported"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> except:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> raise</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">try:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> adminUser = sys.argv[1] </span><br />
<span style="font-family: Courier New, Courier, monospace;"> adminPassword = sys.argv[2] </span><br />
<span style="font-family: Courier New, Courier, monospace;"> adminUrl = sys.argv[3]</span><span style="font-family: 'Courier New', Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> projectName = sys.argv[4]</span><br />
<span style="font-family: Courier New, Courier, monospace;"> exportJar = sys.argv[5]</span><br />
<span style="font-family: Courier New, Courier, monospace;"> customizationFile = sys.argv[6]</span><span style="font-family: 'Courier New', Courier, monospace;"> </span><br />
<span style="font-family: Courier New, Courier, monospace;"> passphrase = "your-passphrase"</span><br />
<span style="font-family: Courier New, Courier, monospace;"> </span><br />
<span style="font-family: 'Courier New', Courier, monospace;"> connect(adminUser, adminPassword, adminUrl) </span><br />
<span style="font-family: Courier New, Courier, monospace;"> domainRuntime()</span><br />
<span style="font-family: Courier New, Courier, monospace;"> exportProject()</span><br />
<span style="font-family: Courier New, Courier, monospace;"><br /></span>
<span style="font-family: Courier New, Courier, monospace;">except:</span><br />
<span style="font-family: Courier New, Courier, monospace;"> print "Unexpected error: ", sys.exc_info()[0]</span><br />
<span style="font-family: Courier New, Courier, monospace;"> dumpStack()</span><br />
<span style="font-family: Courier New, Courier, monospace;"> raise</span><br />
<br />
<h4>
Conclusion</h4>
WLST provides a very powerful and comprehensive scripting environment for Oracle Fusion Middleware products. While most administration and management features can be accessed and executed through WLST, some of the features that are available through IDEs or consoles are not (easily) available through WLST and require a workaround or some research. One of these examples was shown in this blog.Ronald van Luttikhuizenhttp://www.blogger.com/profile/16349079496824277926noreply@blogger.com3Nijmegen, The Netherlands51.8125626 5.837226399999963251.6555996 5.5145028999999628 51.9695256 6.1599498999999636tag:blogger.com,1999:blog-1766203392912336249.post-83998142982797868272014-07-14T21:45:00.001+02:002014-07-14T21:45:48.547+02:00Oracle BPM Suite 12c and SOA Suite 12c at eProseed World 2014As most of you know, Oracle officially released SOA Suite 12c (12.1.3) and BPM Suite 12c (12.1.3) a couple of week ago. Exciting times for people like us, who have worked extensively with BPEL Process Manager, Oracle ESB, SOA Suite 10g, and SOA Suite 11g! The same week that 12c was released, eProseed World 2014 took place. During this event all eProseed employees meet for a fun couple of days full of social and work-related sessions. Because Vennster is merging into the eProseed Netherlands office we will soon migrate this blog to an eProseed domain. For us it was an excellent chance to meet all our new colleagues. In between the tour of Luxembourg city and an afternoon full of Highland Games (nobody got injured :-), multiple sessions where organized to present and discuss Oracle BPM and SOA 12c.<br />
<br />
<br />
<div style="text-align: center;">
<iframe allowfullscreen="" frameborder="0" height="356" marginheight="0" marginwidth="0" scrolling="no" src="//www.slideshare.net/slideshow/embed_code/36924558" style="border-width: 1px 1px 0; border: 1px solid #CCC; margin-bottom: 5px; max-width: 100%;" width="427"> </iframe> </div>
<div style="margin-bottom: 5px;">
<div style="text-align: center;">
<strong> <a href="https://www.slideshare.net/rluttikhuizen/e-proseed-world2014soasuite12cv02" target="_blank" title="eProseed World 2014 - Update on Oracle SOA Suite 12c">eProseed World 2014 - Update on Oracle SOA Suite 12c</a> </strong> from <strong><a href="http://www.slideshare.net/rluttikhuizen" target="_blank">Ronald van Luttikhuizen</a></strong> </div>
</div>
<br />
The SOA Suite 12c presentation included an overview of 10 years of Oracle & SOA, new features and important themes in Oracle SOA Suite 12c, and information on the migration tool bundled with SOA Suite 12c to perform in-flight upgrade from 11g to 12c.<br />
<br />
<br />Ronald van Luttikhuizenhttp://www.blogger.com/profile/16349079496824277926noreply@blogger.com0Luxembourg49.815273 6.129583000000025149.1595375 4.838689500000025 50.471008499999996 7.4204765000000252tag:blogger.com,1999:blog-1766203392912336249.post-43430854118005911242014-05-16T21:07:00.003+02:002014-05-16T21:09:41.895+02:00To Pull or to PushIn a recent project various designs were discussed to integrate business processes implemented in Oracle BPM with a Java front-end application. More specifically, how status changes in these processes could be communicated to the end user via the front-end. The possible scenarios quickly boiled down to a poll versus push approach and various in-between scenarios. This blog lists the various approaches and design considerations.<br />
<br />
<h4>
Case</h4>
The custom-built Java application provides a thin and stateless User Interface that is used by local branch employees to sell products to customers. The process of selling these products is coordinated through a business process that is implemented in Oracle BPM 11g. The configuration of the products for a particular customer is done by the employee through the Java application. After the configuration of the product is completed, the Java application sends a signal to the process. The process will initiate various automated tasks such as credit checking. In the meantime the employee waits until these tasks are executed, then views the results of those checks and continues with the completion of the order.<br />
<br />
The question we discussed is how to inform the employee, though the Java application, that the checks are executed by the process and the employee can move on. We know the milestone in the process is reached through a combination of the occurrence of a particular Human Task and the process state itself.<br />
<br />
<h4>
Solution based on polling</h4>
In a polling approach, the Java front-end application polls for the process status and workflow status every few seconds using the out-of-the-box Oracle BPM and Human Workflow APIs. The client applications poll to see if process instances have reached a particular milestone; if so the application moves forward. Since the Java application is stateless and has no server side, the custom application directly polls from every client session and not from a central web server. This means every new client will increase the load on the BPM platform. Stress tests showed that in this scenario the OBPM engine would be mostly busy handling polling requests and couldn’t accommodate for a high degree of concurrently running process instances.<br />
<br />
The basic polling approach is simple to implement from the perspective of the Java front-end, but not very scalable.<br />
<br />
We could consider optimizing the polling. For example to use a Coherence Grid or Service Bus Result Cache as caching layer between the Java clients and the Oracle BPM APIs and have the clients poll the cache instead of the APIs directly. Upside is that such a cache is easily created and that we limit the number of requests on the backend BPM engine by centralizing the polling requests and using a default caching mechanism. Downside is that the polling results can be outdated when the actual process state has changed and the process status data in the cache is not yet invalidated.<br />
<br />
<h4>
Solution based on pushing</h4>
The Java front-end clients are interested in some status change. For this purpose, a natural approach would be to push an event from the process to the Java clients when that particular milestone is reached. The preferred choice in this scenario would be to use JMS for this since this standard is both supported by Java as well as Oracle BPM 11g through the use of JCA Adapters. The pro of this approach is that it is much more scalable. We only perform an activity (publish an event) when needed, we don’t do useless polling. Downside however in this case is that the front-end application doesn’t support event subscription using JMS and this would require a significant change in that application.<br />
<br />
<h4>
Approach</h4>
We used a three step approach:<br />
<br />
<ul>
<li><b>Short-term</b>. Expose a new service that encapsulates the polling logic. Implement this service on the Service Bus and use Result Caching to cache the polling results. This service is easily created and alleviates the back-end usage of OBPM APIs. The business needs to accept that results can be outdated in some scenarios as a trade-off for the increased load that can be supported.</li>
<li><b>Middle-term</b>. Push events from the BPM process using Mediator and a JCA JMS Adapter when a certain milestone is reached and store the event data in a custom table. Have the Java front-end poll on the custom table. In this approach the process uses events, which is the desired approach. We only need a small change to the Java front-end to poll on the custom table instead of the OBPM engine itself, thereby offloading the engine. The Java front-end however still incurs overhead by using a polling approach. </li>
<li><b>Long-term</b>. Change the custom Java application to support event subscription, for example using JMS. This way the scalability of the front-end application will improve since the number of events is much lower than the number of polling requests. Also, on average the front-end application knows about reaching the milestone faster using events, than it does when periodically polling for that information. </li>
</ul>
<br />
<br />Ronald van Luttikhuizenhttp://www.blogger.com/profile/16349079496824277926noreply@blogger.com0Nijmegen, The Netherlands51.8125626 5.837226399999963251.6555996 5.5145028999999628 51.9695256 6.1599498999999636