Tuesday, 13 January 2015

JDeveloper 12c: Resolving 'MDS-01368: Variable "oracle.home" used in configuration document is not defined' error

 When I started up my Integrated Domain I encountered loads of errors in the log regarding the starting of my ADF application:

...
Caused By: oracle.mds.config.MDSConfigurationException: MDS-01330: Kan MDS-configuratiedocument niet laden.    
MDS-01329: Kan element "persistence-config" niet laden.
MDS-01370: Configuratie van MetadataStore voor metadata-store-usage "mstore-usage_1" is ongeldig.    
MDS-01368: Variabele "oracle.home" in het configuratiedocument is niet gedefinieerd als systeemeigenschap of omgevingsvariabele.

...

I found several questions on the oracle community about this, but none answers. Yet the answer turns out to be quite simple.

It is apparently caused by the adf-config.xml in the workspace where you'll find a snippet like:
                    <metadata-store-usage id="mstore-usage_1">
                        <metadata-store class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
                            <property name="metadata-path" value="${oracle.home}/integration"/>
                            <property name="partition-name" value="seed"/>
                        </metadata-store>
                    </metadata-store-usage>

Here you see that in the metadata-path a reference to the oracle.home property is made.

It turns out that Oracle lacked to add this property in the startup script of the integrated weblogic default domain.

So open the setDomainEnv.cmd (Windows) or setDomainEnv.sh (Linux) script. Under Window for the DefaultDomain of the Integrated Weblogic, it is found in your Roaming Application data similar to: c:\Users\martien\AppData\Roaming\JDeveloper\system12.1.3.0.41.140521.1008\DefaultDomain\bin\

Then find the setting for EXTRA_JAVA_PROPERTIES and add the property -Doracle.home=%SOA_ORACLE_HOME%
Like:
set EXTRA_JAVA_PROPERTIES=%EXTRA_JAVA_PROPERTIES% -Dsoa.archives.dir=%SOA_ORACLE_HOME%\soa -Doracle.home=%SOA_ORACLE_HOME% -Dsoa.oracle.home=%SOA_ORACLE_HOME% -Dsoa.instance.home=%DOMAIN_HOME% -Dtangosol.coherence.log=jdk -Djavax.xml.soap.MessageFactory=oracle.j2ee.ws.saaj.soap.MessageFactoryImpl -Dweblogic.transaction.blocking.commit=true -Dweblogic.transaction.blocking.rollback=true -Djavax.net.ssl.trustStore=%WL_HOME%\server\lib\DemoTrust.jks -Doracle.xml.schema\Ignore_Duplicate_Components=true -Doracle.xdkjava.compatibility.version=11.1.1 -Doracle.soa.compatibility.version=11.1.1

Refire your domain and it should startup smoothly, regarding this issue. Probably it saves you some startup time too.

Build failed: where's my bc4j.xcfg?


Yesterday and this morning I lost a lot of time with building failures, trying to build our ADF HumanTask forms. We used a adf-lib for amongst others XML DataControls, and reusable page-comoponents.

Trying to build the ear file, and actually that adf-lib, I got an error stating 'Unable to copy to output directory ... <default-package>/common/bc4j.xcfg not found'. Indeed in that default ADFBc folder the bc4j.xcfg is not available, nor anywhere in our whole project or workspace.

After a while of searching on our friend Google, I found this post of Andrejus Baranovski.

Apparently in Jdeveloper 11gR2 Oracle introduced a caching mechanism for the IDE.Probably some paging mechanism where Jdeveloper pages files in memory to disk. It's, to be honest, actually one of the behaviours I did not like in Eclipse. I liked the 'what you see is what you edit' approach of JDeveloper.

And since I'm mostly a SOA and BPM developer, I was stuck in JDeveloper 11gR1, never go to R2. But now in 12c I ran into this behaviour of JDeveloper. Anyway, JDeveloper does this caching on Application level, thus on a per Application basis. So go to Application Properties:
 Then to the node IDE Performance Cache:
There you'll find the default location of your cache. In that folder you'll find a .data subfolder, containing caching data of all or some of your Application projects. Close JDeveloper (since under Windows it locks those files) and clear that folder.

Since this folder is a subfolder of the application, by default, you should make sure to ignore it with versioning, override the folder with a path outside of your subversion working copy.

Wednesday, 7 January 2015

Change Subversion password in Jdeveloper

On most projects I used TortoiseSVN voor versioning with Subversion. It gives me a feeling of being more in control of my working copy. In the past I used JDevelopers built in versioning tool on a project, due to lack of administrator rights for installing Tortoise. And although you need to give it some time to get used to it, the versioning is pretty good actually.

On my current project I gave it a go again, since the customer is used to do versioning from inside the IDE (be it Eclipse or JDeveloper).

One thing that I remember to be hard to do was changing your subversion password. I remember that I could not find it in Jdeveloper 11g. And again in Jdeveloper 12c it was hard to find as well. So I started getting affraid to have to hack in the preference or property files. But it turns out that you can do it pretty easy from the tool. Be it that it is at a less obvious place.

In Jdeveloper go to the Team menu and choose Versions.

It will open the Versions Browser or Navigator:
You can right click on the particular connection (in my example the blurred one):

And here you can change your password.
You can also add or remove repository connections, import and export them. Which is handy because in SQLDeveloper there's also a Subversion client. Of course, since it's based on the same framework.


Some versioning features I'm happy about in JDeveloper:
  • The pending changes tools is neat: it gives a nice overview of pending changes divided over tabs with incoming outgoing (your own changes), (updates from coworkers), and candidates (added files that are not versioned yet)
  • Integrated in project navigator in JDeveloper, where you can do changes on file, project and application level.
I'm less happy about or getting used to:
  • Versioning functionality is pretty much scattered over the IDE in different context menu's. Not only because of the different versioning levels, but the preferences are done at different places. See the Versions Navigator above, but I tend to search for preferences in the Preferences menu.
  • There are folders that you don't want to have versioned, for example: files generated at build like compiled classes, processes and jar/war/ear files. You want to be able to set the 'svn:ignore' property for those. But those folders and files tend to be invisible in the project navigator. So you have to add the parent folders of those files and folders as a resource, set the property, commit and remove them as a resource again. 
  • When I want to set keywords (like Id, author, etc.) for svn keyword replacement, JDeveloper doesn't know of the possible values. 
But for most jobs the SVN integration is impressing complete.

Happy versioning in JDeveloper!

Tuesday, 6 January 2015

It's Spring for Oracle ACM API's

Before the holiday season I was working on a service to receive e-mails in BPM using the UMS-email-adapter. Then process the attachments and the body and upload them to the Oracle ACM-case the email was meant for.

I won't get in too much detail here, since there are some articles on the use of ACM-API's like the ones of Niall Comminsky.

Unfortunately, until now, there are no WSDL/SOAP or REST services available on the ACM-API's, as they are on the Workflow Task API's.

However, it is not so hard to make the API's available as services. The trick is to wrap them up in a set of Java-beans, with one class with methods that do the jobs and create 'request and response beans' for the input parameters of the methods and the response.

A few years ago I wrote an article on using Spring components in SOA Suite 11g. This approach is still perfectly usable for SOA/BPM12c. And gives you a WSDL interface on the API's in near to no time.

There is one remark on the API's, though. That is on the creation of the the ACM Stream Service, or actually the creation of the BPMServiceClientFactory to get the context.

In the blog of Niall you'll read that you need to set the following context-properties:

        Map properties =
            new HashMap();
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,
                       BPMServiceClientFactory.REMOTE_CLIENT);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_PROVIDER_URL,
                       "t3://localhost:7001");
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_CREDENTIALS,
                       cPwd);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_SECURITY_PRINCIPAL,
                       cUser);
        caseMgtAPI.mServiceClientFactory =
                BPMServiceClientFactory.getInstance(properties, "default",
                                                    null);
Since in my case the service is running on the same server as the BPEL/BPM/ACM Process Engine is running, there's no need to create a connection (and thus provide an URL) and to authenticate as EJB_SECURITY_PRINCIPAL. So I found that the following suffices:
        Map properties =
            new HashMap();
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.CLIENT_TYPE,
                       WorkflowServiceClientFactory.REMOTE_CLIENT);
        properties.put(IWorkflowServiceClientConstants.CONNECTION_PROPERTY.EJB_INITIAL_CONTEXT_FACTORY,
                       "weblogic.jndi.WLInitialContextFactory");
        BPMServiceClientFactory factory = BPMServiceClientFactory.getInstance(properties, null, null);
I would expect that  'WorkflowServiceClientFactory.REMOTE_CLIENT' should be'WorkflowServiceClientFactory.LOCAL_CLIENT', but need to verify that. The code above works in my case.
Update 12-1-2015: When using LOCAL_CLIENT I get the exception:
oracle.bpm.client.common.BPMServiceClientException: Cannot lookup Local EJB from a client. Try annotating it in the referred EJB. Veroorzaakt door: oracle.bpm.client.common.BPMServiceClientException: Cannot lookup Local EJB from a client. Try annotating it in the referred EJB.
So apparently you need to use REMOTE_CLIENT.

You do need to authenticate with the BPM user that is allowed to query the case, upload documents  etc. as follows:
 context = bpmFactory.getBPMUserAuthenticationService().authenticate(userName, userPassword.toCharArray(), null);
Hope this helps a little further in creating services on ACM.

Wednesday, 17 December 2014

Send HTML Formatted email using SoaSuite 11g/12c

This week I stumbled upon a question on the SOASuite forum, on the Oracle communities, that where the questioner wanted to send HTML-formatted emails.

It happens that I was busy with the email-adapter myself, and it would be nice to have neatly formatted email. It took me some time, but I managed to do it.
It basically consist of:
  1. Define an outbound email adapter config, with Opaque element. This expects an Base64 encoded payload, which enables you to put in everything you want (given it is valid for your receiver)
  2. Create an HTML payload as a string, simply by concatenating all the html code, your content and probaly variable-content.
  3. Use an embedded java activity to unencode the XML encodings and Base64 encode it.
  4. Copy the Base64 encoded payload to the opaque message payload, fill in the subject and the to-email-adres
  5. Invoke the email adapter, with the following properties on the invoke activity:
    1. jca.ums.to -> based on a variable
    2. jca.ums.subject -> based on a variable
    3. jca.ums.msg.content-type -> based on an expression: "text/html"
The last-property is important: it tells the receiving application to interpret the message as html.

Read the complete how-to here.

When I have time, in a later stage I'll update this message to transfer the content to this page.

Monday, 15 December 2014

ora:getAttachmentProperty: Failed to decode properties string

Last week I created a process that polls the usermessagingservice-email adapter to read emails and store the email with attachments as Oracle ACM case documents.

For simple e-mails this works fine, but with some emails I get the error:
0An error occurs while processing the XPath expression; the expression is ora:getAttachmentProperty('Content-Type', 'ReceiveMessage_ReceiveNotification_InputVariable','body', '/ns2:message/ns2:attachment[$AttachmentId]').XPath expression failed to execute.

An error occurs while processing the XPath expression; the expression is ora:getAttachmentProperty('Content-Type', 'ReceiveMessage_ReceiveNotification_InputVariable','body', '/ns2:message/ns2:attachment[$AttachmentId]').

The XPath expression failed to execute; the reason was: java.lang.RuntimeException: Failed to decode properties string ,att.contentId=1,Content-Type=multipart/related;

    boundary "---- _Part_188_790028878.1418047669530",.

Check the detailed root cause described in the exception message text and verify that the XPath query is correct.

XPath expression failed to execute

This occurs with both the functions ora:getAttachmentProperty and ora:getAttachmentContent.

It turns out that attachements that fail, are embedded attachments, like company logo's in autographs. They have a content-type like: "multipart/related", see the propertie string like:
,att.contentId=1,Content-Type=multipart/alternative; 
 boundary "---- _Part_21_137200243.1418648527909",/related;
But 'real' attachments did work, and had a properties string like:
Content-Transfer-Encoding=base64,Content-Disposition=attachment,att.contentId=2,Content-ID=<58BB5695B386104EA778D6E3C982C79D@caci.nl>,Content-Type=image/jpeg; name DataSources.jpg,

Apparently, if the content-type in the properties string does not start with 'multipart', then the attachment is processable.
When you open the BPEL ReceiveMessage_ReceiveNotification_InputVariable input variable I got something like:
  <part xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="body">
      <message xmlns="http://platform.integration.oracle/blocks/adapter/fw/metadata/SWKInboundEmail">
         <attachment href="409425ae-8448-11e4-a413-000c297d0a6d"/>
         <attachment href="409907af-8448-11e4-a413-000c297d0a6d"/>
         <attachment href="4099a3f0-8448-11e4-a413-000c297d0a6d"/>
         <attachment href="409a4031-8448-11e4-a413-000c297d0a6d"/>
         <opaqueElement xmlns="http://xmlns.oracle.com/pcbpel/adapter/opaque/">PGh0bWwgeG1sbnM6dj0idXJuOnNjaGVtYXMtbWljcm9zb2Z0LWNvbTp2bWwiIHhtbG5zOm89InVy
bjpzY2hlbWFzLW1pY3Jvc29mdC1jb206b2ZmaWNlOm9mZmljZSIgeG1sbnM6dz0idXJuOnNjaGVt
YXMtbWljcm9zb2Z0LWNvbTpvZmZpY2U6d29yZCIgeG1sbnM6bT0iaHR0cDovL3NjaGVtYXMubWlj
cm9zb2Z0LmNvbS9vZmZpY2UvMjAwNC8xMi9vbW1sIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv
VFIvUkVDLWh0bWw0MCI+DQo8aGVhZD4NCjxtZXRhIGh0dHAtZXF1aXY9IkNvbnRlbnQtVHlwZSIg
... 
.

In the Soa Infra database a table exists named 'ATTACHMENTS', with three columns: 'KEY', 'ATTACHMENT' and 'PROPERTIES'.

When you do a select on that table where the key the @href attribute, then you'll find the attachment. The PROPERTIES column contains the properties string like mentioned above.

So I created a DB Adapter config, with JNDI name 'eis/DB/SOA' (referring to already configured datasource in the DB Adapter), on this table. In the for-each loop I first query the attachment using the href attribute.

Then I extract the content-type using the expression
substring-before(substring-after($InvokeQuerySoaInfraAttachments_QuerySoaInfraAttachmentsSelect_OutputVariable.AttachmentCollection/ns6:Attachment/ns6:properties, 'Content-Type='),';')

In an IF statement using an expression like
not(starts-with($contentType, 'multipart'))
I only process those attachments that has content-type that is not multipart.

Probably a more sophisticated expression can be found.I could check on a list of only supporting mime-types.

To me this seems like a bug: SOASuite should be able to get the available properties out of the string to be able to process this.The main problem is also that the BPEL fault-handler is ignored: when the error occurs, the process fails! So I can't catch the exception and act on it. And honestly: I should not query the table myself, using the DB adapter, do I?

By the way: working with 12c (12.1.3), but I assume the same will occur in 11g.

Wednesday, 3 December 2014

Integrating BPM12c with BAM

In BPM12c there is a tight integration with BAM, like it was with 11g. However, BAM is not automatically installed in BPM. You need to do that seperately. But having done that, you need to get BPM acquainted with BAM and instruct it to enable process analytics.

For a greater part the configuration is similar to the 11g story. My former oracle colleague wrote a blog about it: 'Configuration of BAM and BPM for process analytics'.
There is a little difference, because in 12c you won't find the mentioned property 'DisableActions' under the 'oracle.as.soainfra.config' -> 'BPMNConfig'. But you have to enable process analytics on the bpm-server(s). The 12c docs tell you how: '11.1 Understanding Oracle BAM and BPM Integration'.
Taken from that document here a short step-list:
  1. Log in to the Fusion Middleware Control (http:Adminserver-host:port/em) console. 
  2. In the Target Navigation pane, expand the Weblogic Domain node. 
  3. Select the domain in which the Oracle BAM server is installed. 
  4. Open the MBean Browser by right-clicking on the domain and select System MBean Browser. 
  5. Expand the Application Defined MBeans node. 
  6. Navigate to oracle.as.soainfra.config node -> 'Server: server_name' -> AnalyticsConfig -> analytics.
  7. Disable the 'DisableProcessMetrics'-property by setting the value to false. 
  8. You might want to do the same with the 'DisableMonitorExpress'-property.
  9. Click Apply.