Sunday, December 1, 2013

First steps into the Oracle Java Cloud

Integration on premise has been there for quite a while. Oracle SOA Suite provides many tools to help customers accomplish that. The area of integration however is expanding. More customers start using cloud services. Integration with cloud services differs in several aspects from on premise integration. Management of servers/accounts differs. Usually there is a limited interface which the cloud provider offers to customize the behavior/scaling of virtual servers/services. Also development differs. You deploy 'to the cloud' and not to a local (on the same network) server. Automation of a business process expands to beyond the borders of the business firewall so security and identity management become more important.

Since this is my first blog post about the Oracle Cloud, I will not go into much detail here but will describe my experience with creating a trial account for the Oracle Java Cloud, deploying a simple helloworld webservice and calling it from outside the cloud.


Requesting an account

I decided to try out the Oracle Java Cloud Service (30 day trial). I requested an account on http://cloud.oracle.com.



While waiting for the confirmation mail, I noticed the chat option. I tried it (after having waited for a while) in order to ask when I would receive this mail since I wanted to get started! An Oracle employee quickly informed me that I should get into touch if after 24h I had not received the e-mail and that the requests would be processed in order of receiving. After about 50h, I received the confirmation e-mail with the activation link;


After activation, the request needed to be processed;


After about 10 minutes I received an e-mail with credentials and I could get started!

The development environment

Getting ready

Luckily there are well documented tutorials available on how to get started with your development environment. I used the following; https://netbeans.org/kb/docs/web/oracle-cloud.html

Getting the environment ready, implied;
- downloading/installing Netbeans
- installing the Oracle Cloud plugin from within Netbeans
- downloading the Oracle Cloud Service SDK
- configuring Netbeans to use the Oracle Cloud account and the Oracle Cloud Service SDK

I created a simple helloworld webservice and made everything ready in order to deploy this to the Oracle Java Cloud.

Deploying

When I tried a deployment, I decided not to use a local Weblogic installation to make things easier but to use a Maven project in Netbeans. Of course things didn't exactly become more easy this way;


That the deployment had failed was also visible in Cloud Service Control, the interface to manage services (the URL was present in the credentials e-mail)


When looking at the deployment log (in bold a typo apparently in the error message);

2013-12-01 08:52:59 CST: weblogic.application.ModuleException: Falied to load webapp: cloudserviceX1X0XSNAPSHOT.war because of DeploymentException: [HTTP:101371]There was a failure when processing annotations for application **** Please make sure that the annotations are valid. The error is Class bytes found but defineClass()failed for: 'ms.test.cloud.testcloudservice'

So I decided to remove some annotations and add a web.xml. I got a new error (again with typo);

2013-12-01 09:20:28 CST: weblogic.application.ModuleException: [HTTP:101064][WebAppModule(cloudserviceX1X0XSNAPSHOT:cloudserviceX1X0XSNAPSHOT.war)] Error parsing descriptor in Web appplication "****"
weblogic.application.ModuleException: Unmarshaller failed
at weblogic.servlet.internal.WebAppModule.loadDescriptor(WebAppModule.java:1349)
at weblogic.servlet.internal.WebAppModule.prepare(WebAppModule.java:375)
at weblogic.application.internal.flow.ScopedModuleDriver.prepare(ScopedModuleDriver.java:180)
at weblogic.application.internal.flow.ModuleListenerInvoker.prepare(ModuleListenerInvoker.java:199)
at weblogic.application.internal.flow.DeploymentCallbackFlow$1.next(DeploymentCallbackFlow.java:518)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:159)
at weblogic.application.internal.flow.DeploymentCallbackFlow.prepare(DeploymentCallbackFlow.java:47)
at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:649)
at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:52)
at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:191)
at weblogic.application.internal.SingleModuleDeployment.prepare(SingleModuleDeployment.java:44)
at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:154)
at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:60)
at weblogic.deploy.internal.targetserver.operations.ActivateOperation.createAndPrepareContainer(ActivateOperation.java:209)
at weblogic.deploy.internal.targetserver.operations.ActivateOperation.doPrepare(ActivateOperation.java:98)
at weblogic.deploy.internal.targetserver.operations.AbstractOperation.prepare(AbstractOperation.java:217)
at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentPrepare(DeploymentManager.java:749)
at weblogic.deploy.internal.targetserver.DeploymentManager.prepareDeploymentList(DeploymentManager.java:1216)
at weblogic.deploy.internal.targetserver.DeploymentManager.handlePrepare(DeploymentManager.java:250)
at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.prepare(DeploymentServiceDispatcher.java:160)
at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentReceiverCallbackDeliverer.java:171)
at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer.java:13)
at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$1.run(DeploymentReceiverCallbackDeliverer.java:47)
at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:545)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)
Caused by: com.bea.xml.XmlException: failed to load java type corresponding to e=web-app@http:/****
at com.bea.staxb.runtime.internal.UnmarshalResult.getPojoBindingType(UnmarshalResult.java:371)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:326)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineTypeForGlobalElement(UnmarshalResult.java:336)
at com.bea.staxb.runtime.internal.UnmarshalResult.determineRootType(UnmarshalResult.java:317)
at com.bea.staxb.runtime.internal.UnmarshalResult.unmarshalDocument(UnmarshalResult.java:168)

When browsing the internet in order to fix my deployment issue, most solutions were related to web.xml versions so I decided to 'downgrade' the web.xml schema used to 2.5 (initially it was 3.1). My new web.xml looked as followed.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5" xmlns="http://java.sun.com/xml/ns/javaee">
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
      <servlet>
    <servlet-name>testcloudservice</servlet-name>
    <servlet-class>ms.test.cloud.testcloudservice</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>testcloudservice</servlet-name>
    <url-pattern>/testcloudservice</url-pattern>
  </servlet-mapping>
</web-app>

Deployment was successful


Also I could access the service at
https://java-trialazsn.java.em1.oraclecloudapps.com/cloudservice/testcloudservice


The service was however secured using Oracle's SSO.

Calling the service outside the cloud

I wondered if I could call the service from for example SOAP UI. In http://docs.oracle.com/cloud/131/developer_services/CSJSU/java-develop.htm#BABHDAJH there were several interesting parts. Mainly the following;

"In Java Cloud Service, the default security posture is "Secured by Default" so any web application, including a SOAP or REST web service application, is secured upon deployment. This also means any web application will have Single Sign-On (SSO) security enabled by default unless you specify otherwise in the web.xml deployment descriptor, as described in Updating the web.xml Deployment Descriptor. In order for "non-browser" web services clients to talk to a web service that is deployed in Java Cloud Service, the web service end point and the WSDL must be made available to the public internet. For more information, see Internet Public Pages."

Oracle provides many authentication mechanisms which allow Cloud services to participate in SSO and to link calls to defined identities. I wanted my sample web service to be public (for this simple test). I noticed the following;

"An application that requires complete public access without any login challenge needs to include an empty <login-config/> element in web.xml."

After following this suggestion, SOAP UI I could now call my service;


Because a public non-secured service running in the cloud is of course often not a good idea, I undeployed my test services.

When undeploying my service, I noticed the following;


I could only request undeployment of one application at a time; I needed to wait for the first undeployment to be finished before initiating the next request. There is a Maven plugin in the Oracle Cloud Service SDK which can be used to automate deployment (see http://www.oracle.com/webfolder/technetwork/tutorials/obe/java/NetBeansMaven/netbeansMaven.html?cid=6947&ssid=1595786280352). I suspect that when doing redeployments/deployments, this is not so much of an issue, but it might be something to take into account when performing undeployments of several applications in a single batch.

Conclusion

There is a lot of documentation available on what you can do with the Oracle Cloud services. Also how to set-up Netbeans and how to secure services is thoroughly described. This makes it relatively easy to get started. I did encounter some errors during first deployment, but they were my own fault...

The monitoring and management software has the same feel as plain old Enterprise Manager and is relatively easy. There are some things different though. You get less control and options inside the Java Cloud Services Control console then for example in Weblogic console or Enterprise Manager Fusion Middleware Control. The Java Cloud job mechanism is new and has some implications, especially when automating builds (good thing a Maven plugin is provided!).

There are some things which will be interesting to dive more deeply into. Securing services and identity management is one of them. Also some Java classes are not available in the cloud. Netbeans indicates this when using a method not available. I do not know yet if there will be many situations in which this limitation will be troublesome. I haven't looked at the Cloud database service yet. This will also be something for future posts.