Showing posts with label BPM Suite. Show all posts
Showing posts with label BPM Suite. Show all posts

Friday, 15 March 2019

JavaDB not bundled anymore with JDK 8, as of U181

Today I was struggling with helping a colleague with a deployment of a SOA Project of his.
I couldn't get it deployed. It seemed I hit the problem described here. However when trying to connect to my Derby DB I got the following error:

I was very surprised. I checked and double checked my config. And check the library:
So, I checked those folders and found that they're not existing!
Now searching around I found in these release notes that as of Update 181 (let it just be the case that I just had this version of the JDK!) Java DB isn't bundled anymore:

Following the links it turns out that you should download it here.


I choose the zip and copied and unzipped it into my jdk:
[oracle@darlin-vce jdk]$ cp /media/sf_Stage/OpenSource/JavaDB/db-derby-10.14.2.0                                                                               -bin.zip .
[oracle@darlin-vce jdk]$ unzip db-derby-10.14.2.0-bin.zip
Archive:  db-derby-10.14.2.0-bin.zip
   creating: db-derby-10.14.2.0-bin/
  inflating: db-derby-10.14.2.0-bin/KEYS
  inflating: db-derby-10.14.2.0-bin/LICENSE
  inflating: db-derby-10.14.2.0-bin/NOTICE
  inflating: db-derby-10.14.2.0-bin/RELEASE-NOTES.html
...

Then I moved/renamed the folder to 'db':
[oracle@darlin-vce jdk]$ mv db-derby-10.14.2.0-bin db
[oracle@darlin-vce jdk]$ ls db/lib/
derbyclient.jar        derbyLocale_it.jar     derbyLocale_zh_TW.jar
derby.jar              derbyLocale_ja_JP.jar  derbynet.jar
derbyLocale_cs.jar     derbyLocale_ko_KR.jar  derbyoptionaltools.jar
derbyLocale_de_DE.jar  derbyLocale_pl.jar     derbyrun.jar
derbyLocale_es.jar     derbyLocale_pt_BR.jar  derbytools.jar
derbyLocale_fr.jar     derbyLocale_ru.jar     derby.war
derbyLocale_hu.jar     derbyLocale_zh_CN.jar
[oracle@darlin-vce jdk]$

After this I'm able to connect to the JavaDB:





So, that was my discovery of the day!

Friday, 26 October 2018

Recursion in XSLT

Last week I helped someone on the Oracle community forums with transforming a comma separated string to a list of elements. He needed this to process each element in BPM Suite, but it is a use case that can come around in SOA Suite or even in Oracle Integration Cloud.

You would think that you could do something like a for-each and trimming the element from the variable.

Recursion

One typical thing with XSLT is that variables are immutable. That means that you can declare a variable and assign a value to it, but you cannot change it. So it is not possible to assign a new value to a variable based on a substring of that same variable.

To circumvent this, you should implement a template that conditionally calls itself until an end-condition is met. This is a typical algorithm called recursion. Recursion is a way of implementing a function that calls itself, for example to calculate the faculty of a number. Recursion can help circumventing the immutability of variables, because with every call to the function you can pass (a) calculated and thus different value(s) through the parameter(s).

I wrote about this earlier, but last week a co-worker asked a similar question, but just the other way around: transforming a list into a comma separated string.

So, apparently it's time to write an article about it.

Transforming CSV to a List

I refactored the xsd's from the question as follows. First the source xsd:
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/Approvals/Source"
            targetNamespace="http://www.example.org/Approvals/Source" elementFormDefault="qualified">
  <xsd:element name="ApprovalRoute" type="tns:approvalRouteByInvoiceNatureResponse"/>
  <xsd:complexType name="approvalRouteByInvoiceNatureResponse">
    <xsd:sequence>
      <xsd:element type="xsd:string" name="approvalRoute" minOccurs="0"/>
      <xsd:element type="xsd:boolean" name="autoApprove" minOccurs="0"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

And the target schema is:
<?xml version="1.0" encoding="windows-1252" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.example.org/Approvals/Target"
            targetNamespace="http://www.example.org/Approvals/Target" elementFormDefault="qualified">
  <xsd:element name="ApprovalRoute" type="tns:ApprovalRouteType"/>
  <xsd:complexType name="ApprovalRouteType">
    <xsd:sequence>
      <xsd:element name="Approver" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

To start with, we have an ApprovalRoute element based on a complex type with the approvalRoute sub-element being the comma-separated list of approvers. Then as a target we have an ApprovalRoute, based on a list of Approver elements.

I generated the following source xml to transform:
<?xml version="1.0" encoding="UTF-8" ?>
<ApprovalRoute xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.example.org/Approvals/Source SOA/Schemas/Approvals-Source.xsd"
               xmlns="http://www.example.org/Approvals/Source">
  <approvalRoute>Approver1,Approver2,Approver3,Approver4,Approver5</approvalRoute>
  <autoApprove>true</autoApprove>
</ApprovalRoute>

Now, we need to split the approvalRoute value in a part before the first comma, and after the first comma. The value before the first comma can be put in an element. But the remainder has to be fed into the same template again. Then, at the end there is no comma in the remainder, so the part before the comma will be empty. There is no comma anymore, so we should not call the template with the remainder, but simply put the remainder in an element. Therefor, the non-existence of the comma can be the end-condition.

Remember, using recursion, you should always have a finalizing condition. To be honest, in my first piece of code in the answer of the question, I forgot about that. But, to my defence: I just put it together by heart and haven't been able to test.

The explanation above results in the following template:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
                xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
                xmlns:tns="http://www.example.org/Approvals/Target"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:ns0="http://www.example.org/Approvals/Source" xmlns:xsl="
                http://www.w3.org/1999/XSL/Transform">
  <!-- https://community.oracle.com/thread/4178385 -->
  <xsl:template match="/">
    <tns:ApprovalRoute>
      <xsl:call-template name="parseDelimitedString">
        <xsl:with-param name="delimitedStr" select="/ns0:ApprovalRoute/ns0:approvalRoute"/>
      </xsl:call-template>
    </tns:ApprovalRoute>
  </xsl:template>
  <xsl:template name="parseDelimitedString">
    <xsl:param name="delimitedStr"/>
    <!-- https://www.w3schools.com/xml/xsl_functions.asp -->
    <xsl:variable name="firstItem" select="substring-before($delimitedStr, ',')"/>
    <xsl:variable name="restDelimitedStr" select="substring-after($delimitedStr, ',')"/>
    <tns:Approver>
      <xsl:value-of select="$firstItem"/>
    </tns:Approver>
    <xsl:choose>
      <xsl:when test="contains($restDelimitedStr, ',')">
        <xsl:call-template name="parseDelimitedString">
          <xsl:with-param name="delimitedStr" select="$restDelimitedStr"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <tns:Approver>
          <xsl:value-of select="$restDelimitedStr"/>
        </tns:Approver>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

(I created this as an XSL Map, but removed the comments that were included by JDeveloper.
I tested this with the following input:
<?xml version="1.0" encoding="UTF-8" ?>
<ApprovalRoute xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.example.org/Approvals/Source SOA/Schemas/Approvals-Source.xsd"
               xmlns="http://www.example.org/Approvals/Source">
  <approvalRoute>Approver1,Approver2,Approver3,Approver4,Approver5</approvalRoute>
  <autoApprove>true</autoApprove>
</ApprovalRoute>

And this resulted in the following output:
<?xml version = '1.0' encoding = 'UTF-8'?>
<tns:ApprovalRoute xmlns:tns="http://www.example.org/Approvals/Target" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/Approvals/Target file:/D:/Projects/2018-ODC/XSL-Demo/XSL-Demo/SOA/Schemas/Approvals-Target.xsd">
   <tns:Approver>Approver1</tns:Approver>
   <tns:Approver>Approver2</tns:Approver>
   <tns:Approver>Approver3</tns:Approver>
   <tns:Approver>Approver4</tns:Approver>
   <tns:Approver>Approver5</tns:Approver>
</tns:ApprovalRoute>

This I used for input for the following xslt.

The other way around: List to CSV

For didactional reasons I'll show the other way around too. Although, we'll see that this can be done easier.

In this case I mean to loop over a series of elements, starting with an index of 1, and adding the elements to a partial string. That means I have 3 parameters:
  • loopApprovers: the parent element, containing all the elements to loop over
  • index: the loop index, with a default of 1
  • partialApprovalRoute: the partial CSV list, defaulted to an empty string

The template loopApprovers can be called with only the approvalRoute. Then with an index of 1, the template is called recursively the first time, with a partialApprovalRoute assigned with the first Approver occurence and an index increased with 1.
For the other occurences where index > 1 and index <= count of elements, the template is called again recursively, but with an increased index and the indexed element added to the partialApprovalRoute separated with a comma.
Then the end situation is when the template is called where index exceeds the count of elements. Then just the partialApprovalRoute is 'returned'  (by the value-of instruction) where it is substringed to a 20000 characters:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
                xmlns:ns0="http://www.example.org/Approvals/Target"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:tns="http://www.example.org/Approvals/Source" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/">
    <tns:ApprovalRoute>
      <tns:approvalRoute>
        <xsl:call-template name="loopApprovers">
          <xsl:with-param name="approvalRoute" select="/ns0:ApprovalRoute"/>
        </xsl:call-template>
      </tns:approvalRoute>
    </tns:ApprovalRoute>
  </xsl:template>
  <xsl:template name="loopApprovers">
    <xsl:param name="approvalRoute"/>
    <xsl:param name="index" select="1"/>
    <xsl:param name="partialApprovalRoute" select="''"/>
    <xsl:choose>
      <xsl:when test="number($index)=1">
        <xsl:call-template name="loopApprovers">
          <xsl:with-param name="approvalRoute" select="$approvalRoute"/>
          <xsl:with-param name="index" select="$index+1"/>
          <xsl:with-param name="partialApprovalRoute" select="$approvalRoute/ns0:Approver[1]"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:when test="number($index)> 1 and number($index)&lt;=count($approvalRoute/ns0:Approver)">
        <xsl:call-template name="loopApprovers">
          <xsl:with-param name="approvalRoute" select="$approvalRoute"/>
          <xsl:with-param name="index" select="$index+1"/>
          <xsl:with-param name="partialApprovalRoute"
                          select="concat($partialApprovalRoute,',',$approvalRoute/ns0:Approver[number($index)])"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="substring($partialApprovalRoute,1,20000)"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Simpler transformation from list to csv

As can be found here for instance, a for-each does not necessarily need to return an element. It can return just a value. So, it can be a bit simpeler:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0"
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xp20="http://www.oracle.com/XSL/Transform/java/oracle.tip.pc.services.functions.Xpath20"
                xmlns:ns0="http://www.example.org/Approvals/Target"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:tns="http://www.example.org/Approvals/Source" 
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <!-- http://p2p.wrox.com/xslt/72164-xslt-need-concatenate-strings-loop-hold-them-later-use.html -->
  <xsl:template match="/">
    <tns:ApprovalRoute>
      <tns:approvalRoute>
        <xsl:call-template name="loopApprovers">
          <xsl:with-param name="approvalRoute" select="/ns0:ApprovalRoute"/>
        </xsl:call-template>
      </tns:approvalRoute>
    </tns:ApprovalRoute>
  </xsl:template>
  <xsl:template name="loopApprovers">
    <xsl:param name="approvalRoute"/>
    <xsl:variable name="approvalRouteCsv">
      <xsl:for-each select="$approvalRoute/ns0:Approver">
        <xsl:value-of select="concat(substring(.,1,20000),',')"/>
      </xsl:for-each>
    </xsl:variable>
    <xsl:value-of select="substring($approvalRouteCsv,1,string-length($approvalRouteCsv)-1)"/>
  </xsl:template>
</xsl:stylesheet>

Conclusion

Understanding Recursion with XSLT will help you with solving much complexer problems in transformations. The last example of transforming a list to a comma separated list is of course structural easier. But the recursive variant allows for more calculations or conditional processing.

Tuesday, 18 September 2018

SOA 12c MDS configuration

In a previous post I described how to have the integrated Weblogic of your SOA/BPM QuickStart refer to the same filebased MDS that you might refer to in the SOADesignTimeRepository in JDeveloper.

These days for my current customer I'm looking into upgrading 11g, as can be read from my previous posts. This customer also has a legacy with projects migrated from 10g.

In the 11g workspace there was a reference to the database MDS in the Development database. In 12c we have a designtime mds reference. I would recommend to refer that to the mds artefacts in your VCS (Version Control System: svn or git) working copy. To do so, call-up the Resources pane in JDeveloper and right click on the SOADesignTimeRepository:
Then navigate to the location in your working copy:
Mind that SOASuite expects an apps folder within this folder, so resulting references in the composite.xml, etc. are expected to start with oramds:/apps/....

Now, I migrated a few projects including a adf-config.xml. In stead of the DB MDS repo, I replaced it with a file-based reference in the adf-config.xml, refering to the SOADesignTimeRepository. If you create a new 12c SOA Application, the adf-config.xml will look like:
<?xml version="1.0" encoding="windows-1252" ?>
<adf-config xmlns="http://xmlns.oracle.com/adf/config" xmlns:adf="http://xmlns.oracle.com/adf/config/properties"
            xmlns:sec="http://xmlns.oracle.com/adf/security/config">
  <adf:adf-properties-child xmlns="http://xmlns.oracle.com/adf/config/properties">
    <adf-property name="adfAppUID" value="MyApplication-1234"/>
  </adf:adf-properties-child>
  <sec:adf-security-child xmlns="http://xmlns.oracle.com/adf/security/config">
    <CredentialStoreContext credentialStoreClass="oracle.adf.share.security.providers.jps.CSFCredentialStore"
                            credentialStoreLocation="../../src/META-INF/jps-config.xml"/>
  </sec:adf-security-child>
  <adf-mds-config xmlns="http://xmlns.oracle.com/adf/mds/config">
    <mds-config xmlns="http://xmlns.oracle.com/mds/config">
      <persistence-config>
        <metadata-namespaces>
          <namespace path="/soa/shared" metadata-store-usage="mstore-usage_1"/>
          <namespace path="/apps" metadata-store-usage="mstore-usage_2"/>
        </metadata-namespaces>
        <metadata-store-usages>
          <metadata-store-usage id="mstore-usage_1">
            <metadata-store class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
              <property name="partition-name" value="seed"/>
              <property name="metadata-path" value="${soa.oracle.home}/integration"/>
            </metadata-store>
          </metadata-store-usage>
          <metadata-store-usage id="mstore-usage_2">
            <metadata-store class-name="oracle.mds.persistence.stores.file.FileMetadataStore">
              <property name="metadata-path" value="${soamds.apps.home}"/>
            </metadata-store>
          </metadata-store-usage>
        </metadata-store-usages>
      </persistence-config>
    </mds-config>
  </adf-mds-config>
</adf-config>

In the metadata-store-usage with id mstore-usage_2 you'll find the reference ${soamds.apps.home} in the metadata-path property. This refers to the folder as choosen in your SOADesignTimeRepository.

Now, I found in the past several times that although the adf-config.xml was similar to the above, that the MDS references did not work. In those cases, as a workaround, I put the absolute path reference in the metadata-path property.

Today I found something similar because of the upgrade, and searched on MDS-01333: missing element "mds-config" This resulted in this article, that gave me the hint.

It turns out that the snippet:
  <adf:adf-properties-child xmlns="http://xmlns.oracle.com/adf/config/properties">
    <adf-property name="adfAppUID" value="MyApplication-1234"/>
  </adf:adf-properties-child>

get's in the way. the UID refers to the application name and some generated number. It turns out not enough to change it the name of the application with a generated number. I haven't found what the proper number should be. So I just removed that snippet and then it worked.

Monday, 17 September 2018

SOA Bundelpatch for 12.2.1.3 available (since juli 2018)

Because of the version level my previous customer was on, I mostly worked with the 12.2.1.2 version of the BPM QuickStart. Recently I started at an other customer that is still on SOA Suite 11g. Since I'm looking into upgrading those the latest 12c version, I installed BPM QuickStart 12.2.1.3 again.

Doing a patch search on support.oracle.com, I found out that juli 17th, 2018, a SOA BundlePatch on 12.2.1.3 was released. It's patch 28300397.

The readme shows quite a list of bugs solved. The version of JDeveloper and the main components stay unaffected. The version changes are shown in the extensions. The vanilla, unpatched, JDeveloper shows:

And the patched JDeveloper shows:

Since it's been a year already since 12.2.1.3 was released (august 2017, if I recollect correctly), this bundle patch is welcome.

By the way, the reason that I was looking into the patches, was that I created a few .xsl files to pre-upgrade our 11g projects. And the didn't reformat properly. JDeveloper behaves strangely, apparenlty it does not recognize an .xsl file as xml. When you copy and paste it into an .xml file it does format properly. I think I have to dig into the preferences to see if this can be tweaked.


To install it, unzip the patch. I'm used to create a patches folder within the OPatch folder in the Oracle Home:
And unzip the patch in to that folder. Because the unzip functionality in Windows is limited to 256 characters in the resulting path names, it is advised to use a tool like 7Zip. Since I use TotalCommander for about everything, (file related that is), I get a neat dialog mentioning this and allowing me to keep the names.

Make sure you have closed JDeveloper.

Then open a command window and navigate to the patches folder:
Microsoft Windows [Version 10.0.17134.285]
(c) 2018 Microsoft Corporation. All rights reserved.

C:\Windows\system32>cd \oracle\JDeveloper\12213_BPMQS\OPatch\patches\28300397

C:\oracle\JDeveloper\12213_BPMQS\OPatch\patches\28300397>set ORACLE_HOME=C:\oracle\JDeveloper\12213_BPMQS

First set the the ORACLE_HOME variable to the location where you installed JDeveloper, C:\oracle\JDeveloper\12213_BPMQS in my case.

Using opatch apply you can apply the patch:
c:\Oracle\JDeveloper\12213_SOAQS\OPatch\patches\28300397>..\..\opatch apply
Oracle Interim Patch Installer version 13.9.2.0.0
Copyright (c) 2018, Oracle Corporation.  All rights reserved.


Oracle Home       : c:\Oracle\JDeveloper\12213_SOAQS
Central Inventory : C:\Program Files\Oracle\Inventory
   from           :
OPatch version    : 13.9.2.0.0
OUI version       : 13.9.2.0.0
Log file location : c:\Oracle\JDeveloper\12213_SOAQS\cfgtoollogs\opatch\opatch2018-09-17_12-05-54PM_1.log


OPatch detects the Middleware Home as "C:\Oracle\JDeveloper\12213_SOAQS"

Verifying environment and performing prerequisite checks...
OPatch continues with these patches:   28300397

Do you want to proceed? [y|n]
y
User Responded with: Y
All checks passed.

Please shutdown Oracle instances running out of this ORACLE_HOME on the local system.
(Oracle Home = 'c:\Oracle\JDeveloper\12213_SOAQS')


Is the local system ready for patching? [y|n]
y
User Responded with: Y
Backing up files...
Applying interim patch '28300397' to OH 'c:\Oracle\JDeveloper\12213_SOAQS'
ApplySession: Optional component(s) [ oracle.mft, 12.2.1.3.0 ] , [ oracle.soa.workflow.wc, 12.2.1.3.0 ] , [ oracle.integ
emina, 2.0.4.0.1 ] , [ oracle.mft.apachemina, 2.0.4.0.1 ] , [ oracle.bpm.plugins, 12.2.1.3.0 ] , [ oracle.oep.examples,
 12.2.1.3.0 ]  not present in the Oracle Home or a higher version is found.

Patching component oracle.soa.all.client, 12.2.1.3.0...

Patching component oracle.integration.bam, 12.2.1.3.0...

Patching component oracle.rcu.soainfra, 12.2.1.3.0...

Patching component oracle.rcu.soainfra, 12.2.1.3.0...

Patching component oracle.soacommon.plugins, 12.2.1.3.0...

Patching component oracle.oep, 12.2.1.3.0...

Patching component oracle.integration.soainfra, 12.2.1.3.0...

Patching component oracle.integration.soainfra, 12.2.1.3.0...

Patching component oracle.soa.common.adapters, 12.2.1.3.0...

Patching component oracle.soa.procmon, 12.2.1.3.0...
Patch 28300397 successfully applied.
Log file location: c:\Oracle\JDeveloper\12213_SOAQS\cfgtoollogs\opatch\opatch2018-09-17_12-05-54PM_1.log

OPatch succeeded.

c:\Oracle\JDeveloper\12213_SOAQS\OPatch\patches\28300397>

Answer 'y' on the questions to proceed and if the oracle home is ready to be patched. And with  opatch lsinventory you can check if the patch (and possibly others) is applied:

c:\Oracle\JDeveloper\12213_SOAQS\OPatch\patches\28300397>..\..\opatch lsinventory
Oracle Interim Patch Installer version 13.9.2.0.0
Copyright (c) 2018, Oracle Corporation.  All rights reserved.


Oracle Home       : c:\Oracle\JDeveloper\12213_SOAQS
Central Inventory : C:\Program Files\Oracle\Inventory
   from           :
OPatch version    : 13.9.2.0.0
OUI version       : 13.9.2.0.0
Log file location : c:\Oracle\JDeveloper\12213_SOAQS\cfgtoollogs\opatch\opatch2018-09-17_12-11-19PM_1.log


OPatch detects the Middleware Home as "C:\Oracle\JDeveloper\12213_SOAQS"

Lsinventory Output file location : c:\Oracle\JDeveloper\12213_SOAQS\cfgtoollogs\opatch\lsinv\lsinventory2018-09-17_12-11-19PM.txt

--------------------------------------------------------------------------------
Local Machine Information::
Hostname: V2W1-MAKKER.ONT.OTA.IND.MINBZK.NL
ARU platform id: 233
ARU platform description:: Microsoft Windows Server 2003 (64-bit AMD)


Interim patches (5) :

Patch  28300397     : applied on Mon Sep 17 12:08:10 CEST 2018
Unique Patch ID:  22311639
Patch description:  "SOA Bundle Patch 12.2.1.3.0(ID:180705.1130.0048)"
   Created on 6 Jul 2018, 01:58:16 hrs PST8PDT
   Bugs fixed:
     26868517, 27030883, 25980718, 26498324, 26720287, 27656577, 27639691
     27119541, 25941324, 26739808, 27561639, 26372043, 27078536, 27024693
     27633270, 27073918, 27210380, 27260565, 27247726, 27880006, 27171517
     26573292, 26997999, 26484903, 27957338, 27832726, 27141953, 26851150
     26696469, 27494478, 27150210, 27940458, 26982712, 27708925, 26645118
     27876754, 24922173, 27486624, 26571201, 26935112, 26953820, 27767587
     26536677, 27311023, 26385451, 26796979, 27715066, 27241933, 24971871
     26472963, 27411143, 27230444, 27379937, 27640635, 26957183, 26031784
     26408150, 27449047, 27019442, 26947728, 27368311, 26895927, 27268787
     26416702, 27018879, 27879887, 27929443

Patch  26355633     : applied on Wed Sep 12 12:00:33 CEST 2018
Unique Patch ID:  21447583
Patch description:  "One-off"
   Created on 1 Aug 2017, 21:40:20 hrs UTC
   Bugs fixed:
     26355633

Patch  26287183     : applied on Wed Sep 12 11:59:56 CEST 2018
Unique Patch ID:  21447582
Patch description:  "One-off"
   Created on 1 Aug 2017, 21:41:27 hrs UTC
   Bugs fixed:
     26287183

Patch  26261906     : applied on Wed Sep 12 11:59:11 CEST 2018
Unique Patch ID:  21344506
Patch description:  "One-off"
   Created on 12 Jun 2017, 23:36:08 hrs UTC
   Bugs fixed:
     25559137, 25232931, 24811916

Patch  26051289     : applied on Wed Sep 12 11:58:45 CEST 2018
Unique Patch ID:  21455037
Patch description:  "One-off"
   Created on 31 Jul 2017, 22:11:57 hrs UTC
   Bugs fixed:
     26051289



--------------------------------------------------------------------------------

OPatch succeeded.

Monday, 23 July 2018

FMW July 2018 patchesets for 11g and 12c releases

I just noticed via community.oracle.com  that bundlepatches and patchset updates for several products in the FusionMiddleware portfolio are released. And thus also for SOA and BPM Suite. You can read more on it in this blog.

Since SOA/BPM Suite 12.2.1.3 is around for quite some time (since fall 2017 I believe) and I've not heard on a 12.2.1.4 or even 18.x release, I found this quite important. So I took a quick look in the patch set for SOASuite 12.2.1.3 and found some interesting patches. I'd recommend applying this one, where some patches seem to apply for the QuickStart as well.

If you're on 12.2.1.2 or earlier, I surely recommend upgrade to 12.2.1.3 and apply this patch set.

Don't spend your summer vacation for it, but schedule it for applying it first thing at return. Or better: do it right before you leave!

Monday, 18 December 2017

Create the SOA/BPM Demo User Community, with just WLST.

As said in my previous post (I've learned somewhere you should not post twice on the same day, but spread it out over time), I'm delivering a BPM 12c training. And based it on the BPM Quickstart. Although nice for UnitTests and development, the integrated weblogic lacks a  proficient set of users to test your task definitions.

Oracle has a demo community and a set of ANT and Servlet based scripts to povision your SOA or BPMSuite environment with a set of American literature writers, to be used in demo's and trainings. I some how found this years ago and had it debugged to be used in 12.1.3 a few years ago. However, I did not know where I got it and if it was free to be delivered.

Apparently it is, and you can find it at my oracle support. Our friends with Avio Consulting also  did a good job in making it available and working with 12c. However, I could not make it work smoothly end 2 end. I got it seeded, but figured that I would not need ANT and a Servlet.

Last year, in 2016, I created a bit of WLST scripting to create users for OSB and have them assigned to OSB Application roles. You can read about that here for the user creation, and here for the app-role assignment.

One thing that's missing in those scripts is the setting of the user attributes. So I googled around and found a means to add those too.

First, I had to transform the demo community seeding xml file to a property file. Like this:

#
cdickens.password=welcome1
cdickens.description=Demo User
cdickens.email=cdickens@emailExample.com
cdickens.title=CEO
cdickens.firstName=Charles
cdickens.lastName=Dickens
cdickens.timeZone=America/Los_Angeles
cdickens.languagePreference=en-US
cdickens.workPhone=100000001
cdickens.homePhone=200000001
cdickens.mobile=300000001
cdickens.im=jabber|cdickens@exampleIM.com

The complete, usersAndGroups.properties file is available here.
In an earlier blog, I wrote about how to read a property file. But my prefered method, does not allow me to determine the property to be fetched dynamically. That's why I split my basic createDemoUsers.properties file, that refers to the usersAndGroups.properties file, and contains the properties refering the Oracle/Jdeveloper home and the connection details for the AdminServer. This property file also contains comma separated lists of users, groups and AppRoles to be created or  granted.

The actual createDemoUsers.py file loops over the three lists and creates the particular users and groups, and grants the AppRoles.

To set the attributes, the setUserAttributeValue of the authenticatorMBean can be used as follows:
    #Set Properties
    firstName=userProps.getProperty(userName+".firstName")
    lastName=userProps.getProperty(userName+".lastName")
    displayName=nvl(firstName, " ")+" "+nvl(lastName, " ")
    authenticator.setUserAttributeValue(userName,"displayName",displayName.strip())

I published the complete set of scripts on the GitHub repo I shared with my colleague.
You can download them all, adapt the createDemoUsers.sh, to refer the correct MW_HOME to your JDeveloper environment. For Windows you might translate it to a .bat/.cmd file.

And of course you can use it for your own set of users.

I think I covered near to all of the Demo User community. Except for management-chains: I could not find how to register a manager for a user in Weblogic. Neither in the console, nor inWLST. So, I currently I conclude it cannot be done. But, if you have a tip, please be so good to leave a comment. I would highly appreciate it.

2018-08-22, Update: found this article referencing the BPM roles, from my appreciated former Whitehorses co-worker. Should be able to integrate this in my scripts.




BPM 12.2.1.3: Exception when deploying BPM project with Human tasks

This week I deliver a BPM 12c Workshop, that I based on the 12.2.1.3 BPM QuickStart. When the students worked on the lab on Human Workflow, they hit an error deploying the Composite, where in the log you can find something like:

Caused By: oracle.fabric.common.FabricException: Error occurred during deployment of component: RequestHolidayTask to service engine: implementation.workflow, for composite: HolidayRequestProcess: ORABPEL-30257
 
exception.code:30257
exception.type: ERROR
exception.severity: 2
exception.name: Error while Querying workflow task metadata.
exception.description: Error while Querying workflow task metadata.
exception.fix: Check the underlying exception and the database connection information.  If the error persists, contact Oracle Support Services.
: exception.code:30257
exception.type: ERROR
exception.severity: 2
exception.name: Error while Querying workflow task metadata.
exception.description: Error while Querying workflow task metadata.
exception.fix: Check the underlying exception and the database connection information.  If the error persists, contact Oracle Support Services.
 
Caused By: oracle.fabric.common.FabricDeploymentException: ORABPEL-30257
 
 
Caused By: java.sql.SQLSyntaxErrorException: Column 'WFTM.PACKAGENAME' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE  statement then 'WFTM.PACKAGENAME' is not a column in the target table.

Apparently in the repository of 12.2.1.3 a column is missing in the Workflow Metadata table.

Luckily, I stumbled upon a question in the community.oracle.com forum that hit this 'bug' as well; and provided a solution. You need to do an alter table to resolve this:
ALTER TABLE SOAINFRA.WFTASKMETADATA ADD PACKAGENAME varchar (200);

The smart guy that provided the answer, used a separate Database UI tool. But fortunately, JDeveloper is perfectly capable to provide you de means as well.

First open the Resource Pallette in JDeveloper. Make sure that you have started your Integrated WebLogic already (since that will run the DerbyDB.

Then in the Resource Pallette, create a new Database Connection:


Provide the following details:
Give it a name, like soainfraDB, as a Connection Type select 'Java DB / Apache Derby'. You can leave Username and Password empty. Then as a Driver Class, choose the 'org.apache.derby.jdbc.ClientDriver' (not the default). Then as a Host Name provide localhost, as a JDBC Port enter 1527 en as  a Database Name enter soainfra.

You can  Test Connection  and then, if Successfull, hit OK.

Then from the IDE Connections pallette  right click your newly created database connection, and choose 'Open in Databases Window':



And from that right click on the database connection and choose 'Open SQL Worksheet':

There you can enter and execute the alter statement:
After this, deployment should succeed. Since it is persisted in the DerbyDB it will survive restarts.

This might apply to the SOA QuickStart as well (did not try).

Friday, 24 November 2017

BPM BAC Subversion Server refusing connections Revised

A little background

In April I wrote about our BPM Server installation, that is actually a single host cluster on dev and test. But installed like it was a dual-node  server, so we had a cloned domain.

A BPM installation has a component that is called the Process Asset Manager. Under the hood it uses a replicated SubVersion server. Each node has one, so they had to synchronize. But since we're on the same host, we needed to differentiate in port numbers. Although we used virtual host names for each server node. In an article in april 'BPM BAC Subversion Server refusing connections' I wrote about that.

It turns out: it did not work appropriately. After some investigation, apparently the bac_node1/subversion server calls the subversion server on bac_node2, with it's own address, but with the port of the other:
...
<Jul 24, 2017, 2:37:29,543 PM CEST> <Debug> <oracle.bpm.bac.svnserver.replication> <darlin01> <bpm_server1> <Active Sync Thread [/54680efc-9328-478e-953c-834bbb250725/]> <<anonymous>> <> <20a54a15-d8d8-4e58-a4f6-11a90e992967-00000008> <1500899849543> <[severity-value: 128] [rid: 0:490:13:19] [partition-id: 0] [partition-name: DOMAIN] > <BEA-000000> <[oracle.bpm.log.Logger:debug] About to synchronize against node Member(Id=2, Timestamp=2017-07-12 08:01:13.309, Address=10.0.0.38:37055, MachineId=9002, Location=site:tst.darwin-it.local,machine:bpm_machine1,process:24566,member:bpm_server2, Role=bpm_cluster), url svn://syncuser@t-bpm-1-bpm-1-vhn.tst.darwin-it.local:8424/54680efc-9328-478e-953c-834bbb250725>
...

Of course there's no listen address so unsurprisingly we get errors like:
...
[2017-05-30T12:55:51.704+02:00] [bpm_server1] [ERROR] [] [oracle.bpm.bac.svnserver.replication] [tid: Active Sync Thread [/b91abb78-6b3d-4448-af6a-e82125f261f0/]] [userId: ] [ecid: ed0bc6ce-fefb-4608-8dbe-46f7206a1573-0000000a,0:527] [APP: OracleBPMBACServerApp] [partition-name: DOMAIN] [tenant-name: GLOBAL] org.tmatesoft.svn.core.SVNException: svn: E210003: connection refused by the server[[
oracle.bpm.bac.subversion.server.repository.exceptions.RepositoryException: org.tmatesoft.svn.core.SVNException: svn: E210003: connection refused by the server
at oracle.bpm.bac.subversion.server.repository.exceptions.RepositoryException.wrap(RepositoryException.java:56)
at oracle.bpm.bac.subversion.server.repository.SVNKitRepositorySession.getRepositoryUUID(SVNKitRepositorySession.java:98)
at oracle.bpm.bac.subversion.server.repository.RepositorySVNSync.sync(RepositorySVNSync.java:74)
at oracle.bpm.bac.subversion.server.repository.RepositorySVNSync.sync(RepositorySVNSync.java:59)
at oracle.bpm.bac.subversion.server.repository.ha.aa.ActiveAARepository$Synchronizer.runImpl(ActiveAARepository.java:341)
at oracle.bpm.bac.subversion.server.repository.ha.aa.ActiveAARepository$Synchronizer.run(ActiveAARepository.java:304)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.tmatesoft.svn.core.SVNException: svn: E210003: connection refused by the server
at org.tmatesoft.svn.core.internal.wc.SVNErrorManager.error(SVNErrorManager.java:85)
at org.tmatesoft.svn.core.internal.wc.SVNErrorManager.error(SVNErrorManager.java:69)
at org.tmatesoft.svn.core.internal.io.svn.SVNPlainConnector.open(SVNPlainConnector.java:62)
at org.tmatesoft.svn.core.internal.io.svn.SVNConnection.open(SVNConnection.java:77)
at org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryImpl.openConnection(SVNRepositoryImpl.java:1252)
at org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryImpl.testConnection(SVNRepositoryImpl.java:95)
at org.tmatesoft.svn.core.io.SVNRepository.getRepositoryUUID(SVNRepository.java:280)
at oracle.bpm.bac.subversion.server.repository.SVNKitRepositorySession.getRepositoryUUID(SVNKitRepositorySession.java:95)
... 5 more
Caused by: java.net.ConnectException: Connection refused (Connection refused)
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:589)
at org.tmatesoft.svn.core.internal.util.SVNSocketFactory.connect(SVNSocketFactory.java:112)
at org.tmatesoft.svn.core.internal.util.SVNSocketFactory.createPlainSocket(SVNSocketFactory.java:68)
at org.tmatesoft.svn.core.internal.io.svn.SVNPlainConnector.open(SVNPlainConnector.java:53)
... 10 more

]] 

(to get this page searchable).

Solution

But now, since this week, Oracle Support presents us.... (drum rolls)  Patch 26775572 for version 12.2.1.2.0, the official fix for this issue, is finally ready and available for download.
I hope to be able to install it next monday. But feel free to try with me: 'Patch 26775572: BAC node using the wrong port when attempts synchronization with Virtual IP '

By the way, for about 2 months we have diagnostic patch running that solves this. But named patch is the official delivery of our diagnostic variant.

By the way, since 12.2.1.3.0 is out in the field for quite some time already, I expect that this did not landed in that version yet. If you're running in the same issue for 12.2.1.3.0 then create a SR to request for a port of this patch.


Wednesday, 15 November 2017

SOASuite 12c: keep running instances using ANT

At my current customer I implemented a poor man's devops solution for Release and Deploy. It was based on a framework created as bunch of Ant projects, that I created years ago. It was based on scripts from Edwin Biemond. See for instance here, here and here. I never wrote about my solution, because although I refactored them quite intensively, the basics were already described thoroughly by him.

What I did was that I modularized the lot, split the environment property files, added logging, added OSB 12c  support, based on the config jar tool, etc.

One thing I ran into this week was that at first deployment from our team to the test environment using my framework, the running instances for the BPM projects were aborted.

Now, if you take a look at the deploy.sarLocation target in Edwin's article about deploying soa suite composites  you'll find that he also supported the overwrite and forceDefault properties.

When re-deploying a composite from JDeveloper you're probably familiar with the 'keep running instances' checkbox. I was looking for the ANT alternative in the ${oracle.home}/bin/ant-sca-deploy.xml scripting. First I looked in the 12c docs (see 47.9.4 How to Use ant to Deploy a SOA Composite Application), but it is not documented there.

But when I opened the particular ant-sca-deploy.xml script I read:
 <condition property="overwrite" value="false">
    <not>
      <isset property="overwrite"/>
    </not>
  </condition>
  <condition property="forceDefault" value="true">
    <not>
      <isset property="forceDefault"/>
    </not>
  </condition>
  <condition property="keepInstancesOnRedeploy" value="false">
    <not>
      <isset property="keepInstancesOnRedeploy"/>
    </not>
  </condition>
 ...
  <target name="deploy">
    <input message="Please enter server URL:" addproperty="serverURL"/>
    <input message="Please enter sar location:" addproperty="sarLocation"/>
    <input message="Please enter username:" addproperty="user"/>
    <input message="Please enter password:" addproperty="password">
      <handler classname="org.apache.tools.ant.input.SecureInputHandler" />
    </input>
    <deployComposite serverUrl="${serverURL}" sarLocation="${sarLocation}" realm="${realm}" user="${user}" password="${password}"
      overwrite="${overwrite}" forceDefault="${forceDefault}" keepInstancesOnRedeploy="${keepInstancesOnRedeploy}"
      regenerateRuleBase="${regenerateRuleBase}" configPlan="${configplan}" scope="${scope}"
      sysPropFile="${sysPropFile}" failOnError="${failOnError}" timeout="${timeout}" folder="${folder}"/>
  </target>

So, the script kindly supports the keepInstancesOnRedeploy property. And thus I implemented a deploy.keepInstancesOnRedeploy property the same way as the deploy.forceDefault/deploy.overwrite properties.

This probably is usefull for Maven based (re-)deployments.

Thursday, 2 November 2017

Enable WebService test client on SOA/BPM production mode environments

At my current assignment I need to trouble shoot the identity service because of a BPM->OID coupling. I use the support document 1327140.1 for it, that suggest to test http://<soa-server>:<port>/integration/services/IdentityService/identity

Doing so in a production mode soa or bpm environment, you'll soon find out that it uses the WebService test client via uri /ws_utc, and that this does not work. Resulting in http-404 Not found errors.

First I found a blog of Maarten of Amis mentioning this as well. But unfortunately, he could not get around it either. But luckily I found note 1915317.1, that tells me that the WebServices test Client is not enabled by default.

You can enable it on your domain via the EM:

And then expand the Advanced node:


Check the 'Enable Web Service Test Page' check box.

Since it is about a production mode environment, you need to 'lock & edit'. The note suggests to do that in the /console and then do the change in /em. And back in /console do the activate. I found that peculiar, since you can do it in the change center in /em as well.

You need to restart the servers (apparently including the AdminServer) to get this in effect.

So now lunch and check if my restart worked.

Thursday, 6 April 2017

BPM BAC Subversion Server refusing connections

These days I work on setting up several development lifecycle environments for BPM, SOA and OSB. What means that we setup servers for Development and test, culminating eventually in supporting the setup of the acceptance and production servers.

Since we want to have development resemble production as much as possible, we installed a dual-node clustered BPM environment, including BAM. However, since it is development, we have the two Managed Servers per cluster on the same phsyical (actually virtual) host.

In 12c BPM introduced a new component the Process Asset Manager, as described here. But installing BPM on a dual node cluster on a single host, will give problems with the underlying BAC/Subversion Component.

Errors you could encounter in the logs are for example:

Status of Start Up operation on target /Domain_o-bpm-1_domain/o-bpm-1_domain/BPMComposer is STATE_FAILED
[Deployer:149193]Operation "start" on application "BPMComposer" has failed on "bpm_server2".
java.lang.RuntimeException: weblogic.osgi.OSGiException: Could not find bundle with Bundle Symbolic Name of:org.tmatesoft.svn.core
               at weblogic.osgi.internal.OSGiAppDeploymentExtension.prepare(OSGiAppDeploymentExtension.java:273)
               at weblogic.application.internal.flow.AppDeploymentExtensionFlow.prepare(AppDeploymentExtensionFlow.java:25)
               at weblogic.application.internal.BaseDeployment$1.next(BaseDeployment.java:727)
               at weblogic.application.utils.StateMachineDriver.nextState(StateMachineDriver.java:45)
               at weblogic.application.internal.BaseDeployment.prepare(BaseDeployment.java:239)
               at weblogic.application.internal.EarDeployment.prepare(EarDeployment.java:66)
               at weblogic.application.internal.DeploymentStateChecker.prepare(DeploymentStateChecker.java:158)
               at weblogic.deploy.internal.targetserver.AppContainerInvoker.prepare(AppContainerInvoker.java:65)
               at weblogic.deploy.internal.targetserver.operations.ActivateOperation.createAndPrepareContainer(ActivateOperation.java:229)
               at weblogic.deploy.internal.targetserver.operations.StartOperation.createAndPrepareContainer(StartOperation.java:95)
               at weblogic.deploy.internal.targetserver.operations.StartOperation.doPrepare(StartOperation.java:108)
               at weblogic.deploy.internal.targetserver.operations.AbstractOperation.prepare(AbstractOperation.java:241)
               at weblogic.deploy.internal.targetserver.DeploymentManager.handleDeploymentPrepare(DeploymentManager.java:794)
               at weblogic.deploy.internal.targetserver.DeploymentManager.prepareDeploymentList(DeploymentManager.java:1340)
               at weblogic.deploy.internal.targetserver.DeploymentManager.handlePrepare(DeploymentManager.java:267)
               at weblogic.deploy.internal.targetserver.DeploymentServiceDispatcher.prepare(DeploymentServiceDispatcher.java:177)
               at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.doPrepareCallback(DeploymentReceiverCallbackDeliverer.java:186)
               at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer.access$000(DeploymentReceiverCallbackDeliverer.java:14)
               at weblogic.deploy.service.internal.targetserver.DeploymentReceiverCallbackDeliverer$1.run(DeploymentReceiverCallbackDeliverer.java:47)
               at weblogic.work.SelfTuningWorkManagerImpl$WorkAdapterImpl.run(SelfTuningWorkManagerImpl.java:666)
               at weblogic.invocation.ComponentInvocationContextManager._runAs(ComponentInvocationContextManager.java:348)
               at weblogic.invocation.ComponentInvocationContextManager.runAs(ComponentInvocationContextManager.java:333)
               at weblogic.work.LivePartitionUtility.doRunWorkUnderContext(LivePartitionUtility.java:54)
               at weblogic.work.PartitionUtility.runWorkUnderContext(PartitionUtility.java:41)
               at weblogic.work.SelfTuningWorkManagerImpl.runWorkUnderContext(SelfTuningWorkManagerImpl.java:640)
               at weblogic.work.ExecuteThread.execute(ExecuteThread.java:406)
               at weblogic.work.ExecuteThread.run(ExecuteThread.java:346)
Caused by: java.lang.RuntimeException: Could not find bundle with Bundle Symbolic Name of:org.tmatesoft.svn.core
               at weblogic.osgi.internal.OSGiAppDeploymentExtension.attachToApplicationBundleClassloader(OSGiAppDeploymentExtension.java:161)
               at weblogic.osgi.internal.OSGiAppDeploymentExtension.prepare(OSGiAppDeploymentExtension.java:249)
               ... 26 more
 
[Deployer:149034]An exception occurred for task [Deployer:149026]start application BPMComposer on bpm_cluster.: weblogic.osgi.OSGiException: Could not find bundle with Bundle Symbolic Name of:org.tmatesoft.svn.core.

Or during deployment of OracleBPMBACServerApp on one of the managed servers:
[2015-02-04T07:04:05.848+00:00] [BPM_Ms1_2] [ERROR] [] [oracle.bpm.bac.svnserver] [tid: [ACTIVE].ExecuteThread: '29' for queue: 'weblogic.kernel.Default (self-tuning)'] [userId: ] [ecid: 88957d95-82b2-4365-aaea-ac834a54599d-00000003,0] [APP: OracleBPMBACServerApp] Unexpected error starting BAC SVN Server.[[
oracle.bpm.bac.subversion.server.exception.ServerException: java.net.BindException: Address already in use

WLS version: 12.1.3.0.0
authentication-provider: default
Servers: AdminServer+ local_bpel_ms1 + local_bpel_ms2
Cluster: local_bpel_cluster, cluster-messaging-mode: unicast

Configuration manager:
Protocol: PLAIN
Topology: ACTIVE_ACTIVE_CLUSTER


As described in Doc ID 1987120.1 on Oracle Suppport, this is due to the fact that by default in oracle.bpm.bac.server.mbeans.metadata MBean the Bac Admin node and the BacNode use the same ports. (I think the cause is a bit mis-phrased in the note....)

To solve this:
  1. Login to Enterprise Manager console : http://host:port/em
  2. Expand WebLogic Domain
  3. Right click on the domain and click on System MBean Browser
  4. In System MBean Browser search for: oracle.bpm.bac.server.mbeans.metadata and expand it
  5. Expand the first BacNode and check that the AdminPort and also the BacNode port are different:
  6. Do the same thing for the second BacNode:
  7. Make sure that all 4 ports are different.
  8. Do a netstat on the machine and check also that the ports used by BAC servers are not already in use. Change them if necessary.
Port check can be done by:
[oracle@darlin-vce-bpm logs]$ netstat -tulpn |grep 8323
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 192.168.1.239:8323      0.0.0.0:*               LISTEN      23940/java
tcp        0      0 192.168.1.240:8323      0.0.0.0:*               LISTEN      23988/java
[oracle@darlin-vce-bpm logs]$ netstat -tulpn |grep 8424
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 192.168.1.240:8424      0.0.0.0:*               LISTEN      23988/java
[oracle@darlin-vce-bpm logs]$ netstat -tulpn |grep 8423
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
tcp        0      0 0.0.0.0:8423            0.0.0.0:*               LISTEN      23940/java
[oracle@darlin-vce-bpm logs]$
You see that the latest port, the AdminPort belonging to the empty AdminAddress on the bpm_server1 is listening on 0.0.0.0, in affect on every address. Apparently, it is not possible to set an explicit address. Since it is on one actual host, the bpm servers are attached to different virtual IP addresses.

Now, this enabled us to start both the OracleBPMBACServerApp  as well as the BPMComposer.
But when we started using the BPM Composer and opening a project and process, there were issues. We found that when you got in bpm_server2, all went well. But when the load balancer directed you to bpm_server1, you could get a Internal server error

We encountered the following errors in the diagnostic log on bpm_server1:
[2017-04-05T03:25:27.270+02:00] [bpm_server1] [NOTIFICATION] [] [oracle.bpm.bac.svnserver.configuration] [tid: Active Sync Thread [/b91abb78-6b3d-4448-af6a-e82125f261f0/]] [userId: <anonymous>] [ecid: 41a5a471-1881-4527-8638-c344af778e7c-0000000a,0:497] [APP: OracleBPMBACServerApp] [partition-name: DOMAIN] [tenant-name: GLOBAL] Default repository path: /u02/oracle/products/fmw/user_projects/domains/o-bpm-1_domain/bpm/bac/bpm_server2/repositories
[2017-04-05T03:25:27.273+02:00] [bpm_server1] [NOTIFICATION] [] [oracle.bpm.bac.svnserver.configuration] [tid: Active Sync Thread [/b91abb78-6b3d-4448-af6a-e82125f261f0/]] [userId: <anonymous>] [ecid: 41a5a471-1881-4527-8638-c344af778e7c-0000000a,0:497] [APP: OracleBPMBACServerApp] [partition-name: DOMAIN] [tenant-name: GLOBAL] Default repository path: /u02/oracle/products/fmw/user_projects/domains/o-bpm-1_domain/bpm/bac/bpm_server1/repositories
[2017-04-05T03:25:27.277+02:00] [bpm_server1] [ERROR] [] [oracle.bpm.bac.svnserver.replication] [tid: Active Sync Thread [/b91abb78-6b3d-4448-af6a-e82125f261f0/]] [userId: <anonymous>] [ecid: 41a5a471-1881-4527-8638-c344af778e7c-0000000a,0:497] [APP: OracleBPMBACServerApp] [partition-name: DOMAIN] [tenant-name: GLOBAL] org.tmatesoft.svn.core.SVNException: svn: E210003: connection refused by the server[[
oracle.bpm.bac.subversion.server.repository.exceptions.RepositoryException: org.tmatesoft.svn.core.SVNException: svn: E210003: connection refused by the server
        at oracle.bpm.bac.subversion.server.repository.exceptions.RepositoryException.wrap(RepositoryException.java:56)
        at oracle.bpm.bac.subversion.server.repository.SVNKitRepositorySession.getRepositoryUUID(SVNKitRepositorySession.java:98)
        at oracle.bpm.bac.subversion.server.repository.RepositorySVNSync.sync(RepositorySVNSync.java:74)
        at oracle.bpm.bac.subversion.server.repository.RepositorySVNSync.sync(RepositorySVNSync.java:59)
        at oracle.bpm.bac.subversion.server.repository.ha.aa.ActiveAARepository$Synchronizer.runImpl(ActiveAARepository.java:360)
        at oracle.bpm.bac.subversion.server.repository.ha.aa.ActiveAARepository$Synchronizer.run(ActiveAARepository.java:304)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.tmatesoft.svn.core.SVNException: svn: E210003: connection refused by the server
        at org.tmatesoft.svn.core.internal.wc.SVNErrorManager.error(SVNErrorManager.java:85)
        at org.tmatesoft.svn.core.internal.wc.SVNErrorManager.error(SVNErrorManager.java:69)
        at org.tmatesoft.svn.core.internal.io.svn.SVNPlainConnector.open(SVNPlainConnector.java:62)
        at org.tmatesoft.svn.core.internal.io.svn.SVNConnection.open(SVNConnection.java:77)
        at org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryImpl.openConnection(SVNRepositoryImpl.java:1252)
        at org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryImpl.testConnection(SVNRepositoryImpl.java:95)
        at org.tmatesoft.svn.core.io.SVNRepository.getRepositoryUUID(SVNRepository.java:280)
        at oracle.bpm.bac.subversion.server.repository.SVNKitRepositorySession.getRepositoryUUID(SVNKitRepositorySession.java:95)
        ... 5 more
Caused by: java.net.ConnectException: Connection refused (Connection refused)
        at java.net.PlainSocketImpl.socketConnect(Native Method)
        at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
        at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
        at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
        at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
        at java.net.Socket.connect(Socket.java:589)
        at org.tmatesoft.svn.core.internal.util.SVNSocketFactory.connect(SVNSocketFactory.java:112)
        at org.tmatesoft.svn.core.internal.util.SVNSocketFactory.createPlainSocket(SVNSocketFactory.java:68)
        at org.tmatesoft.svn.core.internal.io.svn.SVNPlainConnector.open(SVNPlainConnector.java:53)
        ... 10 more

]]

This occurs just on one of the two servers, in our case bpm_server1. Apparently, the Bac server can't run more than once on the same host. Or, in an active-active configuration, one of the bpm servers does not know how to connect. I don't know yet, how it is supposed to work internally.

Toggling the configuration to Single node won't work. Restarting the servers will cause the bpm composer unable to start at all. But switching to active passive in the BacConfigurationManager helped:

Then restarted the bpm servers and the BPM Composer and the underlying PAM/Bac/Subversion were working on both servers.


Thursday, 12 January 2017

Property expansion under windows.

A little over a year ago I wrote an article about automatic scripted installation of the SOA and BPM QuickStarts. One thing I wanted to improve is to be able to dynamically expand properties in the response file. I already found out how to do that under Linux but most QuickStart installations are done under Windows. So how to 'how to replace properties in textfile in Windows'?

I found this StackOverflow question, and favored the PowerShell option, so I modified that answer to be able to expand the ORACLE_HOME property in the response file.

I modified the response file that I got from the manual installation wizard of the BPM QuickStart as follows:
[ENGINE]

#DO NOT CHANGE THIS.
Response File Version=1.0.0.0.0

[GENERIC]

#Set this to true if you wish to skip software updates
DECLINE_AUTO_UPDATES=true

#My Oracle Support User Name
MOS_USERNAME=

#My Oracle Support Password
MOS_PASSWORD=<SECURE VALUE>

#If the Software updates are already downloaded and available on your local system, then specify the path to the directory where these patches are available and set SPECIFY_DOWNLOAD_LOCATION to true
AUTO_UPDATES_LOCATION=

#Proxy Server Name to connect to My Oracle Support
SOFTWARE_UPDATES_PROXY_SERVER=

#Proxy Server Port
SOFTWARE_UPDATES_PROXY_PORT=

#Proxy Server Username
SOFTWARE_UPDATES_PROXY_USER=

#Proxy Server Password
SOFTWARE_UPDATES_PROXY_PASSWORD=<SECURE VALUE>

#The oracle home location. This can be an existing Oracle Home or a new Oracle Home
ORACLE_HOME=${ORACLE_HOME}



I saved this as bpmqs1221_silentInstall.rsp.tpl. Then I created a simple command file called expandProperties.bat with the following content:
set ORACLE_HOME=c:\oracle\jdeveloper\12212_bpmqs
set QS_RSP=bpmqs1221_silentInstall.rsp
set QS_RSP_TPL=%QS_RSP%.tpl
powershell -Command "(Get-Content %QS_RSP_TPL%) -replace '\$\{ORACLE_HOME\}', '%ORACLE_HOME%' | Out-File -encoding ASCII %QS_RSP%"

This does the following:
  1. Set the ORACLE_HOME environment variable. This is what I also do in the QuickStart install script. The content of this variable should replace the '${ORACLE_HOME}' property in the response file template.
  2. Set QS_RSP to the Response File name
  3. Set QS_RSP_TPL to the Response File Template name
  4.  Call Powershell with a command line command using the '-Command' argument
    1. Read the template file denoted with %QS_RSP_TPL%' using the Get-Content argument.
    2. Replace the occurrences of the string  '${ORACLE_HOME}' with the value of the corresponsing environment variable '%ORACLE_HOME%'. But since the input is considered as a regular expression. Thus the special characters $, { and } need to be prefixed with a backslash.
    3. 'Pipe' the output to the output file denoted with %QS_RSP%. It's important to add -encoding ASCII for the encoding. Otherwise its apparently encoded in UTF in a way the Oracle Installer does not comprehend.
Run this as:
Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>expandProperties.bat

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>set ORACLE_HOME=c:\oracle\jdeveloper\12212_bpmqs

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>set QS_RSP=bpmqs1221_silentInstall.rsp

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>set QS_RSP_TPL=bpmqs1221_silentInstall.rsp.tpl

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>rem powershell -Command "(gc bpmqs1221_silentInstall.rsp.tpl) -replace '\$\{ORACLE_HOME\}', 'c:\oracle\jdeveloper\12212_bpmqs' | Out-File -encoding ASCII bpmqs1221_silentInstall.rsp"

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>powershell -Command "(Get-Content bpmqs1221_silentInstall.rsp.tpl) -replace '\$\{ORACLE_HOME\}', 'c:\oracle\jdeveloper\12212_bpmqs' | Out-File bpmqs1221_silentInstall.rsp"

c:\Data\Zarchief\Stage\FMW\bpm12cR2QS>

This creates a new file named bpmqs1221_silentInstall.rsp, where the content of the last line is changed to:
...

#The oracle home location. This can be an existing Oracle Home or a new Oracle Home
ORACLE_HOME=c:\oracle\jdeveloper\12212_bpmqs

Just what I need...

Monday, 2 January 2017

A good year for the Clouds

At last we stumbled into a new year. New rounds, new chances as we say in Dutch. I ended 2016 and start 2017 on a project that involved the implementation of several Oracle Cloud products, where I'm responsible for ICS and PCS. But I also did several on-premise projects. So from a current Integration/Process Cloud implementation what to think about Oracle's Cloud plans?

Last fall, one of my managers came home from a presentation where Oracle's on-premise products were declared to be deceased. According to the presenter Oracle announced that they will focus only on Cloud and no new functionality would be introduced into the on-premise products.

But honestly, I don't believe any of the 'SOA/BPM Suite on-premise is dead'-announcements. And if I turn out to be wrong in the end, I tend to call it a foolish decision.

I find it perfectly reasonable that Oracle mainly focuses on  Cloud these days. Of course Oracle needs to grow into a first-class Cloud Provider. Thus that Oracle decides to bring out new functionality first into PCS and ICS and possibly SOACS makes perfectly sense. For every functionality they need to think about how, in terms of UI,  to provide it in the Cloud product as well. But keep in mind that PCS runs on the exact same process engine as BPEL and BPMN. And that the exact same counts for Business Rules engine. So changes in those components eventually benefits the on-premise counterparts.

I remember that when I joined Oracle almost 20 years ago, I learned that Larry Ellison declared that we don't need the guys with the glue-guns, since Oracle had E-Business Suite. Which caters for everything a company might need in a software system. But customers turned out to have very plausible and good reasons (at least in their own opinion... 😉 ) to choose for E-Business Suite  for financials and Siebel for CRM or other solutions for particular functional areas. And those products need to be integrated. Oracle eventually understood that and provided InterConnect back then. And later introduced BPEL Process Manager and SOASuite.

Nowadays more and more enterprises are looking to Cloud Solutions for parts of their businesses. But will keep using on-premise solutions for other parts. Some companies still need to keep their datacenters for parts of the IT. Possibly because of the need for several other products that are only available in an on-premise variant. Maybe for regulatory reasons. Or maybe other very plausible reasons, for instance those that are agreed on the golf-course or tennis-court...

So I think Oracle can't get around providing on-premise versions of Fusion Middleware.

What I do think, and really hope, is that On-premise and cloud will grow towards each other. Years ago (back in 2009, I still have emails to back it up) I was in a conversation with a Product Manager and SOA Architect, about how BPM in the cloud could work while connecting to services in the data center. I envisioned a service like with Log Me In, where a local agent connects to the Services in the Cloud that provides control, introspection and call-outs to the local services.

Now in ICS we have the concept of on-premise agents, which is actually a light-weight Weblogic that allows you to connect Cloud Integrations with on-premise services. Although this agent is a good thing, along the lines of my earlier visions, I think it can be better. What about an cloud/on-premise-integration layer in the Fusion Middleware infrastructure?

In the PCS configuration panes you can provide the URLs to your Integration Cloud Service and Document Cloud Service subscriptions. That enables you to introspect into your Integrations and seamless integration with DOCS. I'd like to see that with FMW Infrastructure (the Weblogic+ installation which is the basis for SOASuite, OSB, etc.) you get a configuration pane in which you could provide the details of your cloud subscriptions. The FMW Infrastructure could have functionality similar to the current ICS Agents. It could connect independently to the particular cloud services and register itself there. You could register wsdls for local third-party services. But if you install OSB or SOASuite or other FMW components it natively gets information on all the services that are deployed to that FMW environment. And then from ICS or PCS you could introspect those. When you connect with JDeveloper to that environment you could introspect into the services and processes in ICS and PCS, to call them from your SOA/BPM composites or OSB services. Just like how you'd do that with local composites or services. That would give you a convenient and transparent experience.

If Oracle could build that into the FMW Infrastructure the boundaries would fade, and FMW would grow into the sky, and the clouds would come down to earth.  I'd like that. I hope a Product Manager of Oracle will pick this up. I would happily exchange thoughts about this.

But above all I hope you have a great 2017. Enjoy this new year with all its great potential.


Friday, 24 June 2016

A couple of notes of the automatic generation of a SOA Suite/OSB domain

Earlier you could have enjoyed my article on the automatic generation of a SOA/OSB domain. Earlier this week I encountered some issues with a domain created at a customer this way.

I got the change to dive into that this week and luckily not only I learned a lot again, but I found the problem as well. I adapted my scripts. I won't repost them completely, I've created a github account, and try to place them there in the near future.

But I'll cover the changes, especially those that caused the problems.

Enrollment


When you create a domain using the config.sh/.cmd wizard, and choose to configure the nodemanager, you'll be asked for the nodemanager user and password. You'll get a per domain nodemanager for free and the domain is enrolled for the nodemanager for you. You might need to adapt the nodemanager.properties in <domain_home>/nodemanager and set the property SecureListener to false. The default is true, while in the Machine definition in the domain the nodemanager/machine is configured to SSL. If you disable the SecureListener, you need to set the property in the wls-console under Machines to Plain instead of SSL. And adapt the listener-port.

The docs on configuring the nodemanager for 12.2.1 can be found here. One of the biggest changes between 11g and 12cR1 is that in 12cR2 you get a per domain nodemanager, with a nodemanager home in the domain home, instead of a nodemanager home in the FMW_HOME, the home of the binaries. Also in the bin folder of the domain you'll find scripts to start and stop the nodemanager.

So for a domain configured in the config-wizard, you need little to do to get the nodemanager working.

But using the scripts in my previous article, you'll find that although a nodemanager password file is created, something is missed for a proper startup of your servers using the nodemanager. You'll find that although the nodemanager starts, connecting to it using nmConnect(), fails with: a message like:
WLSTException: Error occured while performing nmConnect : Cannot connect to Node Manager. : Access to domain 'osb_domain' for user 'weblogic' denied.

You can go to the Domain->security settings in the weblogic console, and change the nodemanager password, but apparently this is not enough. You'll need to explicitly enroll the domain against the nodemanager. To do so:
  • Start the AdminServer, using the startWebLogic.sh/.cmd script in the domain home.
  • Start wlst.sh/.cmd
  • Connect to the AdminServer using:  connect(adminUser, adminPwd, adminURL)
  • Perform an NodeManager Enroll using: nmEnroll(soaDomainHome, nodeManagerHome)
  •  Stop the AdminServer
  • (Re)Start the nodemanager
  • In wlst: Connect to the nodemanager using nmConnect(....)
  • Perform nmStart('AdminServer')
The following enrollDomain.py script might help:
#############################################################################
# Create a SOA/BPM/OSB domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2016-06-23
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = 'enrollDomain.py'
#
#Home Folders
soaDomainHome   = domainsHome+'/'+soaDomainName
nodeManagerHome = soaDomainHome+'/'+'nodemanager'
#
#
lineSeperator='__________________________________________________________________________________'
#
#
def usage():
  print 'Call script as: '
  print 'Windows: wlst.cmd '+scriptName+' -loadProperties localhost.properties'
  print 'Linux: wlst.sh '+scriptName+' -loadProperties environment.properties'
  print 'Property file should contain the following properties: '
  print "adminUrl=localhost:7101"
  print "adminUser=weblogic"
  print "adminPwd=welcome1"
#
#
def main():
  try:
    #
    # Section 1: Base Domain + Admin Server
    print (lineSeperator)
    print ('Enroll '+soaDomainName+' for NodeManager')
    print('\nConnect to AdminServer ')
    print (lineSeperator)
    adminURL=adminListenAddress+':'+adminListenPort
    connect(adminUser, adminPwd, adminURL)
    #
    print('\nPerform nmEnroll')
    print (lineSeperator)
    #
    nmEnroll(soaDomainHome, nodeManagerHome)
    #
    print ('\nFinished')
    #
    print('\nExiting...')
    exit()
  except NameError, e:
    print 'Apparently properties not set.'
    print "Please check the property: ", sys.exc_info()[0], sys.exc_info()[1]
    usage()
  except:
    apply(traceback.print_exception, sys.exc_info())
    stopEdit('y')
    exit(exitcode=1)
#call main()
main()
exit()

It can be called with a shell script (enrollDomain.sh) like:
#!/bin/bash
. fmw12c_env.sh
echo
echo Enroll domain
wlst.sh enrollDomain.py -loadProperties darlin-vce-db-osb.properties

I also adapted the function 'createUnixMachine' in the createSoaBpmDomain.py script:
#
# Create a Unix Machine
def createUnixMachine(serverMachine,serverAddress, serverPort, nmType):
  print('\nCreate machine '+serverMachine+' with type UnixMachine')
  print (lineSeperator)
  cd('/')
  create(serverMachine,'UnixMachine')
  cd('UnixMachine/'+serverMachine)
  create(serverMachine,'NodeManager')
  cd('NodeManager/'+serverMachine)
  set('ListenAddress',serverAddress)
  set('ListenPort',int(serverPort))
  set('NMType',nmType)
This allows for the non-default setting of the nodemanager to another listen port and nodemanager type, based on the following properties in the property file:
#
# Server Settings
nmType=Plain
server1Machine=darlin-vce-db
server1Address=darlin-vce-db
server1Port=5555
server2Enabled=false
server2Machine=darlin-vce-db
server2Address=darlin-vce-db2
server2Port=5555
An example of the property file can be found in the earlier article: automatic generation of a SOA/OSB domain.

Logging

In the example property file in my scripts you can set a location for the logging:
# Logs
logsHome=/u01/app/work/logs

If this is a absolute path, 'nothing is on the hand'. Your domain should start correclty. But if you choose to use a relative path, like 'logs', then starting the AdminServer might succeed (in my case) but starting the managed servers fail with a 'No such file or directory' message:
wls:/nm/osb_domain> nmStart('Adminserver')
 
Starting server Adminserver ...
 
Traceback (innermost last):
 
  File "<console", line 1, in ?
 
  File "<iostream", line 188, in nmStart
 
  File "<iostream>", line 553, in raiseWLSTException
 
WLSTException: Error occurred while performing nmStart : Error Starting server Adminserver : Received error message from Node Manager Server: [Server start command for WebLogic server 'Adminserver' failed due to: [No such file or directory]. Please check Node Manager log and/or server 'Adminserver' log for detailed information.]. Please check Node Manager log for details.
 
Use dumpStack() to view the full stacktrace :
 
wls:/nm/osb_domain

Now it turns out that this is caused by the JavaArgs that are generated and set in the script. I found that if you set JavaArgs you need to set redirects for weblogic.Stdout and weblogic.Stderr, like:
'-XX:PermSize=256m -XX:MaxPermSize=512m -Xms1024m -Xmx1532m -Dweblogic.Stdout='+logsHome+'AdminServer.out -Dweblogic.Stderr='+logsHome+'AdminServer_err.out'

Where logFolder should be an absolute path. This has to do with the context in which the nodemanager is starting the server. From that context the relative reference apparently does not evaluate to the proper location.
You can however, leave the Java args empty. So I changed my scripts to not use the getServerJavaArgs function, anymore, but get them from the property file. I replaced the xxxJavaArgsBase  with xxxJavaArgs variables. And left them empty.

The configurator doesn't set the JavaArgs, it leaves them over to the setDomain.sh/.cmd and setStartupEnv.sh/.cmd. If you do so, you can use a relative path, and the servers will start properly.

Wednesday, 15 June 2016

Automatic Patching of SOA/BPM QuickStarts

Earlier I wrote how to automatically install the SOA/BPM QuickStarts. Actually, I'm quite busy with doing automatic/scripted installs for SOA/BPM Suite and OSB, as you might have read.

At my current customer we encountered that in the last months there are many one-off-patches released on support.oracle.com. We selected a pretty large bunch of patches and apply them one by one is a tedious job. But the thing is with these automatic installs that you want to have a uniform installation for each developer so each developer should have the same patches installed, in the same location. And you probably want to be able to quickly do a re-install to a uniform setup.

So I figured out how to do a silent install of the patches and to do this in a loop.

Out of the selected patches I found 5 catechories:
  • 001: JDeveloper patches, where only a few we found possibly applicable for the SOA/BPM QuickStarts
  • 002: ServiceBus related patches
  • 003: SOA Suite merged patches
  • 004: SOA Suite related other patches
  • 005: BPM Suite merged patches
  • 006: BPM Suite related patches
So I divided the patches in those 5 folders ('001', '002', ... , '005'). And I numbered them in 3 digit folders, since my scripting needed to figure out the patch number from the path name. Each patch is a zip with a sub-folder with only the patch number (without the 'p'). So the path-lengths needed to be equal (so not 'jdev' and 'soa' or 'osb').

I have one main script called 'installQSPatches.bat' that loops over the files in each sub-folder:
@echo off
rem check SOA12.2 QS
setlocal
set FMW_HOME=C:\oracle\JDeveloper\12210_BPMQS
set ORACLE_HOME=%FMW_HOME%
set SOA_PATCH_SOURCE=SOA
set SOA_PATCH_HOME=%FMW_HOME%\Opatch\patches
set CUR_DIR=%~dp0
echo Current Dir: %CUR_DIR%
if exist "%FMW_HOME%" goto :SOAQS_HOME_EXISTS
echo %FMW_HOME% not installed yet! Install first!
goto :DONE
:SOAQS_HOME_EXISTS
echo %FMW_HOME% exists, install Patches
echo ____________________________________________________
call %FMW_HOME%\wlserver\server\bin\setWLSEnv.cmd
echo ____________________________________________________
:JDEV_PATCHES
echo -
echo JDeveloper Patches
echo ____________________________________________________
for %%f in (001\*.zip) do (
  echo %%f
  call applyPatch %%f 
)
:SB_PATCHES
echo -
echo ServiceBus Patches
echo ____________________________________________________
for %%f in (002\*.zip) do (
  echo %%f
  call applyPatch %%f 
)
:SOA_MERGE_PATCHES
echo -
echo SOA Suite Merged Patches
echo ____________________________________________________
for %%f in (003\*.zip) do (
  echo %%f
  call applyPatch %%f 
)
:SOA_PATCHES
echo -
echo SOA Suite Patches
echo ____________________________________________________
for %%f in (004\*.zip) do (
  echo %%f
  call applyPatch %%f 
)
:BPM_MERGE_PATCHES
echo -
echo BPM Suite Merged Patches
echo ____________________________________________________
for %%f in (005\*.zip) do (
  echo %%f
  call applyPatch %%f 
)
:BPM_PATCHES
echo -
echo BPM Suite Patches
echo ____________________________________________________
for %%f in (006\*.zip) do (
  echo %%f
  call applyPatch %%f 
)
:DONE
echo Done installing patches
endlocal
You need to shutdown JDeveloper and IntegratedWeblogic before starting this script.
And it needs to be started in an elevated (as Administrator) command window.

For each patch it calls the applyPatch.bat script:
set PATCH=%1
set PATCH_NR=%PATCH:~5,8%
echo ____________________________________________________
echo Check Patch %PATCH% for patch nr %PATCH_NR%
if exist "%FMW_HOME%\Opatch\patches\%PATCH_NR%" goto :PATCH_EXISTS
echo "%FMW_HOME%\Opatch\patches\%PATCH_NR%" does not exist.
set SOA_PATCH_HOME=%FMW_HOME%\Opatch\patches
rem set SOA_PATCH_HOME=c:\temp\patches
echo .. Unzip %SOA_PATCH_SOURCE%\%PATCH% to %SOA_PATCH_HOME%
call ant -f ant-zip.xml unzip -Dzip-file=%PATCH% -Dunzip-destination=%SOA_PATCH_HOME%
cd %ORACLE_HOME%\Opatch\patches\%PATCH_NR%
echo  .. Apply %ORACLE_HOME%\Opatch\patches\%PATCH_NR%
call %ORACLE_HOME%\Opatch\opatch apply -silent
cd %CUR_DIR%
goto :DONE
:PATCH_EXISTS
echo Patch %PATCH_NR% already exits!
:DONE
echo Done for patch %PATCH_NR%
echo ____________________________________________________

This one figures out what the patchnumber (%PATCH_NR%) is based on the patch-file-name, and if that patch already exists in the %FMW_HOME%/Opatch/patches folder. If not it will unzip the patch file to that folder, resulting in a sub-folder named with the patch number. Then it will apply the patch using Opatch in silent mode.
For the unzip, it uses a simple ANT build file, since the Windows Command screen does not support a commandline-unzip (as far as I could find). The ANT script is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<project name="zip" default="zip" basedir=".">

 <target name="zip">
  <zip destfile="${zip-file}.zip" basedir="${folder-to-zip}" excludes="dont*.*" />
 </target>

 <target name="unzip">
  <unzip src="${zip-file}" dest="${unzip-destination}" />
 </target>

</project>

When I finished this I thought I should convert it to a complete ANT script. But maybe later.

The selected patches for 12.2.1:
The selected JDeveloper patches (sub-folder 001) were:
  • 22283405    JDEV 12.2.1 - NULLPOINTEREXCEPTION ENCOUNTERED (Patch)
  • 23266774    VALIDATION ERRORS WHEN CLICKING ON MANDATORY FIELDS IN JDEV12.2.1 (Patch)
  • 22463346    NOT STRESS SOA: MULTIPLE ERROR MESSAGES OF DEFINITIONMANAGER.LOCKINGLOGGER (Patch)
  • 21890657    CREATE REST THROWS ERROR 500 FOR REFERENCED ENTITY (Patch)
These are not all the possible JDeveloper patches and even may not apply to developing SOA/BPM or SB processes or services.

The selected Service Bus patches (sub-folder 002) were:
  • 23223332 Need to provide a holistic solution in main line for Bug 22887808
  • 21824551 NPE while trying to read OWSM keystore
  • 21168191 UnsupportedOperationException from ServiceAccountRuntimeCache
  • 23184618 Http Transport throws NullPointerException
  • 21827583 Deploying existing .sbar with Maven
  • 22738111 OSB Java Call out method's not visible from JDeveloper
  • 20119834 need to trim headers size if size exceeds 998 characters.
  • 22358699 OSB12C fn-bea:inlinedXML does not work properly
  • 22374613 In 12.2.1 the OSB Projet pom files still says 12.1.3
  • 20196110 JDev OSB Extension has missed export Split-Join and Proxy Flow as png
  • 22187224 OSB 12.2.1 - MessageID changes between request and response messages
  • 22392646 Maven could not be used in Jdev in 12.2.1.0.0
  • 22602059 12C: OSB pipeline based on XML - $body structure incomplete - missing node
  • 22276364 12C: OSB pipeline based on XML - $body structure unavailable
  • 21659900 OSB removes WSA headers on outbound request 
 The selected SOA Suite merged patches (sub-folder 003) were:
  • 23543517 MERGE REQUEST ON TOP OF 12.2.1.0.0 FOR BUGS 23527297 22875806 22995356 23062804
  • 23138916 MERGE REQUEST ON TOP OF 12.2.1.0.0 FOR BUGS 21549249 21572567
  • 23106839 MERGE REQUEST ON TOP OF 12.2.1.0.0 FOR BUGS 21826430 22912570
  • 23134140 Diagnostic Tracking Bug for Bug 23108573 v2
The selected SOA Suite regular patches (sub-folder 004) were:
  • 23056585 XQuery transformation is not showing all the types of XSD in the design view
  • 21904101 Error when running ValidateComposite to project with bpel calling HWF
  • 23205706 MALFORMEDURLEXCEPTION EXCEPTION ON JDEV 12.2.1.0.0 - BAM 12C IDE CONNECTION
  • 23193066 BPEL polls from UMS Adapter results in too large CONVERSATION_ID error
  • 21698320 SELECTING ELEMENT IN LARGE DOCUMENT TAKES FREEZES 2+MINUTES
  • 23108573 TrackingContextProperty causes ClassCastException in SOA 12c Spring Composite
  • 21925552 SOA Maven Plugin requires deploying sar to server when running mvn install
  • 23186275 JDeveloper 12.2.1 JMS Adapter not displaying Elements from the imported xsd file
  • 22337707 Naming conflict with EDN event subscribers from single Mediator component
  • 23052343 16.2.3 : WS JOB REQUEST ENDS UP IN ERROR STATE WHEN INVOKED VIA OTD URL
  • 22026475 JDEV : Adapter : Nullpointerexception while creating the BPEL Process
  • 22815366 Unable to use WSDL containing an unsupported Notification Operation portType
  • 22978098 Indicators configured on Response payload coming from a DB ADapter do not work
  • 21835972 SFTP FileListing not work as expected. Need similiar bug fix as in bug 21176154
  • 22648699 SOA Suite12.2.1-JCA files not getting updated with Configuration Plan values
  • 22300448 JDeveloper doesn't add a libraries file group to existing SOA deployment profile
  • 16548396 Can not emulate fault from the SOA Test UI
Of these the patches 21925552 conflicts with 21904101 and 23193066 conflicts with 23108573. So you should choose which one you want to apply.

For BPM (sub-folder 005) the following merged patches were selected:
  • 22571194 NPE in o.bpm.project.sca.loader.impl.ElementContainer:82
  • 23283093 NPE in o.bpm.project.sca.loader.impl.ElementContainer:198
For BPM (sub-folder 006) the following patches were selected:
  • 22191778 In the Business Architecture Modeling links section, buttons are missing
  • 21325503 12c compilation err-crm: oracle.bpm.services : extncontentpublicmodeleventaction
  • 22736087 BPM Workspace not refreshing the task list after Initiator task page is closed
  • 22018713 MeasurementPublisher has been optimized
  • Software 22217468 Refresh is not working properly in Impact Analysis Report - 500 error
  • 22018703 MIAuditLog has been optimized
  • 22690780 workspace Title & logo unchanged on loginpage after patch 22272135
  • 19536412 Case Service handles namespaces incorrectly in SOAP XML messages
  • 22348182 EDG RC3a :Task comments cannot be added
  • 22087208 When approving a task it immediately opens the next task in your tasklist
  • 22753983 12c e-manager authorization issues - List view
  • 22111729 BPM instance is not released after completing an HT ith the voting patern
  • 22581888 Configure global option to enable task details to appear as pop-up window in 12c
  • 23077279 Composer crash when creating Org Unit or Application system for human task
  • 23125361 REST hrefs for attachments containing spaces in their names do not work.
  • 23205514 Flexfields not properly displayed in parallel task with SDO
  • 23301503 weblogic user or Administrator group shouldn't be necessary to login to composer
  • 23491602 Studio generated project_properties.wsdl missing the correlation mapping
  • 21792613 NOT STRESS BPM REST:get WebFormService - no valid constructor error 
 From these the 22581888 conflicts with 22087208. And  23205514 conflicts with 22348182.

Download the applicable patches for your situation and put them in the appropriate folder. If you use the SOA QuickStart in stead of  BPM QuickStart, you should skip the BPM Related patches of course.
UPDATE september 26th, 2016: Since this is a Windows script: you need to run this on the same drive as the QuickStart installer. It does a change dir to the patch and then an 'Opatch apply'. But if it's not run on the same drive, the change dir succeeds, but it's on another drive so still not current.