Darwin IT

Subscribe to Darwin IT feed
Darwin-IT professionals do ICT-projects based on a broad range of Oracle products and technologies. We write about our experiences and share our thoughts and tips.Martien van den Akkerhttps://plus.google.com/110503432901891966671noreply@blogger.comBlogger357125
Updated: 14 hours 59 min ago

Introducing Darwin Oracle Type Accelerator

Mon, 2017-05-08 06:37

Years ago, I created a set of XSL templates and queries to create object types out of queries on the datadictionary of the Oracle Database. It only did basic types on tables, and selects on those. I wrote an article on it that still can be downloaded here. Later, I extended the framework to also do inserts and updates and follow foreign keys. The thing with foreignkeys is that you can handle them a as a detail-tables like Order Lines with an Order. Or lookup, like a place of birth, or country of origin, etc.

I must say I was quite pleased with what it could do.

Lately I stumbled on a question on community.oracle.com that ran about updating multiple tables using the database adapter. Normally you would need to do multiple invokes of a Database Adapter definitions, at least one per table, to do inserts and or updates.  I created thus because Oracle Types are a very powerful means to get data from a datamodel with multiple tables in just one invoke. Or insert data into it. You just create a pl/sql procedure with a parameter based on the root object. The database adapter wizard creates the accompanying XSD's and you only need to do a proper mapping in to the input variable and do the invoke. In the Pl/Sql procedure you call the particular method (sel, ins, upd) of the root object, that propagates into all the child and lookups. Most of the times that is enough. In more complex models, you might enhance the calling pl/sql.

I'm happy to announce that a moment ago I put my source on Github. I renamed it to Darwin Oracle Type accelerator. I did not have the change to create elaborate documentation. But in short:

  • In $GitHub/Dotacc/Source/Dotacc/ddl/owner\ you'll find setup scripts for the framework.
  • With setupTables.sql and setupPlsql.sql you create a bunch of tables and pl/sql with XXX_ as a prefix to support the generation of types.
  • insertXslNL2.0.sql or insertXslEN2.0.sql creates the xsl in the xxx_xmldocuments table.
  • $GitHub/Dotacc/Source/Dotacc/Config contains a set of insert scripts to define what tables, foreignkeys etc. to handle: 
    • XXX_TABLES: defines the tables for which you want to generate the types. The column generation_order defines in which order the types are created or dropped at recreation. 
    • XXX_FK_DEFINITIONS: defines the foreignkeys to consider. The FK_TYPE column defines if it should be considered as a child table ('DETAIL') or Lookup ('LOOKUP'). 
    • XXX_DERIVED_COLUMNS: defines virtual columns that can be looked up from another table. You can define a method that is added to do the actual lookup based on a lookup value from a key column. 
    • XXX_CUSTOM_METHODS: can be used to add custom methods to the object type.
    • I added two datamodels (Doe_owner and hbc_owner under ddl) as a sample model. It would be nice to come up with a sample filling for named tables.
To do a recreate of the types, perform:
execute  xxx_gen_objects.recreate_objects;

 If you have remarks, post a comment on the blog and/or do a request to contribute on github or send me a PM on community.oracle.com.

List Weblogic 12c System Components

Thu, 2017-05-04 07:30
Besides starting and stopping servers, it turns out handy to be able to list the particular system components of a Weblogic domain. For most domains, you might have an embedded/colocated Oracle HTTP server.
But we're also busy with installing BI publisher domains, and there several BI Components are created. To list which ones are created (and determine where things might went wrong) it might be handy to list all the system components. For that I created the following script. For the referenced fmw12c_env.sh and fmw.properties, I refer to Start and stop a WebLogic (SOA/OSB) Domain.

The wlst script is listSystemComponents.py:
#############################################################################
# List System Components of FMW Domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2017-04-20
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = sys.argv[0]
#
#
lineSeperator='__________________________________________________________________________________'
pad=' '
#
#
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:7001"
print "adminUser=weblogic"
print "adminPwd=welcome1"
#
# Connect To the AdminServer
def connectToAdminServer(adminUrl, adminServerName):
print(lineSeperator)
print('Try to connect to the AdminServer')
try:
connect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, url=adminUrl)
except NameError, e:
print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
print('Try to connect to the AdminServer adminUser and adminPwd properties')
connect(adminUser, adminPwd, adminUrl)
#
# Get the Servers of Domain
def getSystemComponents():
print(lineSeperator)
print('\nGet SystemComponents from domain')
serverConfig()
cd("/")
sysComponents = cmo.getSystemComponents()
return sysComponents
#
# Boolean to string
def bool2str(bool):
result='false'
if bool:
result='true'
return result
#
# Descr system component type
def descSysCompType(sysComponentType):
result=sysComponentType
if sysComponentType=='OHS':
result='Oracle HTTP server'
elif sysComponentType=='OBIPS':
result='BI Presentation Service'
elif sysComponentType=='OBIS':
result='BI Server'
elif sysComponentType=='OBISCH':
result='BI Scheduler'
elif sysComponentType=='OBICCS':
result='BI Cluster Controller'
elif sysComponentType=='OBIJH':
result='BI JavaHost'
else:
result=sysComponentType
return result
#
# Start clusters
def showSystemComponents():
print(lineSeperator)
print ('Show SystemComponents')
sysComponents=getSystemComponents()
#
if (len(sysComponents) > 0):
print('SystemComponent '[:30]+'\t'+'Type '[:20]+'\tAutoRestart\tMachine')
for sysComponent in sysComponents:
sysCompName = sysComponent.getName()
sysCompNamePad=sysCompName+pad
sysCompType=descSysCompType(sysComponent.getComponentType())
sysCompTypePad=sysCompType+pad
machine=sysComponent.getMachine()
if machine is None:
machineName = 'None'
else:
machineName = machine.getName()
print sysCompNamePad[:30]+'\t'+sysCompTypePad[:20]+'\t'+bool2str(sysComponent.getAutoRestart())+'\t\t'+machineName
else:
print('No SystemComponents found!')
#
print ('\nFinished showing SystemComponents.')
#
# Main
def main():
try:
#
print(lineSeperator)
print('\nConnect to the AdminServer: '+adminServerName)
connectToAdminServer(adminUrl, adminServerName)
#
showSystemComponents()
#
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())
exit(exitcode=1)
#call main()
main()
exit()

To call this easily for different environments I have the following bash listSystemComponents.sh script:
#!/bin/bash
#############################################################################
# List Domain System Components using wlst
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2017-04-19
#
#############################################################################
#
. fmw12c_env.sh
export ENV=$1
echo
echo "List Domain System Components"
wlst.sh ./listSystemComponents.py -loadProperties ${ENV}.properties

I introduced an ENV variable here, so you can call it as:
[oracle@darlin-vce scripts]$ ./listSystemComponents.sh fmw

This exends the fmw argument with '.properties'. So if you want to use this for different environments, just copy the fmw.properties to a bip-acc.properties file or something like that and adapt the properties. Then using it against that environment is as calling:

[oracle@darlin-vce scripts]$ ./listSystemComponents.sh bip-acc

Single Sign On for Apex with ADFS? With Weblogic 12c and ORDS: Yes, you can!

Tue, 2017-05-02 11:41
Lately we implemented a Single Sign On solution for Apex, based on Weblogic 12cR2, ORDS 3.0.9, and ADFS as a federated Identity Provider. This combination turns out to be a marriage of 3 different worlds. So we ran in to a several issues that were not described in one simple how-to document. So in this document I try to assemble the information needed to do the end 2 end configuration (apart from the OHS configuration).

For most of the SAML2 configuration on Weblogic, we could have my earlier article  on SAML2.0 on Weblogic 11g, as a guide: Service Provider initiated SSO on WLS11g using SAML2.0 .

This helped a great deal with regards to ADFS and 12c. The rest of the issues I'd like to cover here, for future reference.
ORDSORDS can be installed in the regular way. I downloaded ORDS and unzipped it in the weblogic domain home. Then I did the setup using:
[oracle@darlin-vce-db ords309]$ java -jar ords.war setup

Then create the i.war containing the Apex and ORDS images. First copy the Apex images from the Apex home to the ORDS images folder. And then create the i.war:
[oracle@darlin-vce-db ords309]$ java -jar ords.war static /u01/data/oracle/config/domains/SP_domain/ords309/images

It is important to provide a complete/absolute path to the this command. This command creates an i.war that contains a reference to the images folder. You can see this as a virtual directory configuration as you would do in Apache/Oracle HTTP Server. It in fact only contains a web.xml, sun-web.xml and a weblogic.xml that contain a reference to that folder. For instance, the weblogic.xml contains:
<weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/weblogic-web-app">
<!-- This element specifies the context path the static resources are served from -->
<context-root>/i</context-root>
<virtual-directory-mapping>
<!-- This element specifies the location on disk where the static resources are located -->
<local-path>/u01/data/oracle/config/domains/SP_domain/ords309/images</local-path>
<url-pattern>/*</url-pattern>
</virtual-directory-mapping>
</weblogic-web-app>

Before deploying the ords.war and i.war files to Weblogic (with Custom Roles), you'll need to make a manual adjustment to the ords.war.
The thing is that ORDS must be instructed to hand over the authentication to Weblogic. To do so, you'll need to add the following to the WEB-INF/web.xml file in the ords.war:
    <!-- Security Constraint -->
<security-constraint>
<web-resource-collection>
<web-resource-name>SecurePages</web-resource-name>
<description>These pages are only accessible by authorized users.</description>
<url-pattern>/f/*</url-pattern>
<!-- <http-method>GET</http-method> -->
</web-resource-collection>
<auth-constraint>
<description>These are the roles who have access.</description>
<role-name>Anonymous</role-name>
</auth-constraint>
<user-data-constraint>
<description>This is how the user data must be transmitted.</description>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- Login Config -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>myrealm</realm-name>
</login-config>
<security-role>
<role-name>Anonymous</role-name>
</security-role>

In WEB-INF/weblogic.xml add the security-role-assignment for the role Anonymous:
<weblogic-web-app  xmlns="http://xmlns.oracle.com/weblogic/weblogic-web-app" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://xmlns.oracle.com/weblogic/weblogic-web-app
http://xmlns.oracle.com/weblogic/weblogic-web-app/1.6/weblogic-web-app.xsd"> <!-- Weblogic 12c -->
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
<session-descriptor>
<persistent-store-type>replicated_if_clustered</persistent-store-type>
</session-descriptor>
<security-role-assignment>
<!--<role-name>valid-users</role-name> -->
<role-name>Anonymous</role-name>
<principal-name>users</principal-name>
</security-role-assignment>
<context-root>/ords</context-root>
</weblogic-web-app>
This is necessary, because after the Authentication using SAML2, the Rolemapper kicks in. And that one has to find a valid role.
APEX-Schema's
APEX uses REST-calls to fetch the images. It is important that all the database users relating to ORDS and APEX are unlocked, that passwords are known. Check for each of the following schema's if you can logon with the known password.

  • ORDS_PUBLIC_USER
  • APEX_PUBLIC_USER
  • APEX_LISTENER
  • APEX_REST_PUBLIC_USER
  • ORDS_METADATA
Then perform the following steps from doc 2075837.1:
  1. Go into the directory where the extracted the full installation of APEX resides
  2. Login to SQLPlus as the SYS user (as sysdba)
  3. Rerun the @apex_rest_config.sql script to recreate the "connect through" privileges for the installation:
    @apex_rest_config
  4. Hit enter for the APEX_LISTENER and APEX_REST_PUBLIC_USER password prompt. (passwords apparently not used for this script)
  5. Verify with the following statement that the connect through grant is present:
    select * from dba_proxies
    where proxy='APEX_REST_PUBLIC_USER'
    and client='APEX_PUBLIC_USER';
  6. If the grant is still missing the customer should verify that the file apex_rest_config_core.sql contains the following statement and run the script again.
    -- Allow REST user to proxy into APEX_PUBLIC_USER for built-in RESTful Services
    alter user APEX_PUBLIC_USER grant connect through ^RESTUN.;
ORDS Validation
From ORDS 3.0.5 onwards ORDS expects a column in the table ords_metadata.apex_pool_config called pool_name. So you could end up with an ORDS installation/configuration that seems to work, but you might not get the Apex application images shown. This is described in this community question. If the applications images don't show up:
  1. Validate that this column exists, through a describe of the table, and check if the table contains any rows.
  2. If necessary, perform the following to chreate the column and fill the table:
cd /u01/data/oracle/config/domains/SP_domain/ords309
java -jar ordsname.war validate

APEX Authentication Schema
To have the Apex application use the authenticated user from Weblogic/ADFS, the authentication scheme needs to be changed. 
This has to be done in a way that in the authentication scheme (shared components --> security --> authentication) APEX fetches the user from the  REMOTE_USER header variable: 


Weblogic 12 and ADFSADFS will use SHA-256 for signing by default. But WLS currently does not support that for SAML2. Although for many other services WLS does 'know' how to do SHA-256. I found articles how to update the policies for OWSM to use SHA-256. But I could not find how to do the same for the SAML2 configuration of Weblogic. So have ADFS do the signing with SHA-1. This might seem not secure, but when using TLS this is a minor thing. Although Weblogic 12c should solve this, in my opinion. See also this blog on Weblogic with ADFS, point 5 under the Takeway or Gotchas.

Another thing we found is that ADFS expects a valid 'https://' url to the ServiceProvider for the entity-id. A regular unique string does not suffice. ADFS apparently checks this URL to be valid. So I used the default TLS-url to the Oracle HTTP server that I used to reverse proxy to the SP Weblogic.

Lastly, in ADFS we needed to add an extra explicit claim had to fill the urn:mace:dir:attribute-def:uid saml2-attribute. This is needed for the identy mapper.

Identity Mapper Class
I updated the IdentityMapper class that I used in my earlier blog. I found a little bug in determining the actual identity/username, that apparently did not occur in 11g. But I also refactored the class a bit, to my latest Java knowledge, for as far as applicable.

package nl.darwinit.wls.saml;

import com.bea.security.saml2.providers.SAML2AttributeInfo;
import com.bea.security.saml2.providers.SAML2AttributeStatementInfo;
import com.bea.security.saml2.providers.SAML2IdentityAsserterAttributeMapper;
import com.bea.security.saml2.providers.SAML2IdentityAsserterNameMapper;
import com.bea.security.saml2.providers.SAML2NameMapperInfo;

import java.security.Principal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Logger;

import weblogic.logging.LoggingHelper;

import weblogic.security.service.ContextHandler;


public class WLSSaml2IdentityMapper implements SAML2IdentityAsserterNameMapper, SAML2IdentityAsserterAttributeMapper {
public static final String ATTR_PRINCIPALS = "com.bea.contextelement.saml.AttributePrincipals";
public static final String ATTR_USERNAME = "urn:mace:dir:attribute-def:uid";
private Logger lgr = LoggingHelper.getServerLogger();
private final String className = "nl.darwinit.wls.saml.WLSSaml2IdentityMapper";
//

/**
* Map Name Info to String
* @param saml2NameMapperInfo
* @param contextHandler
* @return
*/
@Override
public String mapNameInfo(SAML2NameMapperInfo saml2NameMapperInfo, ContextHandler contextHandler) {
final String methodName = className + ".mapNameInfo";
debugStart(methodName);
String user = null;
debug(methodName, "saml2NameMapperInfo: " + saml2NameMapperInfo.toString());
debug(methodName, "contextHandler: " + contextHandler.toString());
debug(methodName, "contextHandler number of elements: " + contextHandler.size());
// getNames gets a list of ContextElement names that can be requested.
String[] names = contextHandler.getNames();
// For each possible element
for (String element : names) {
debug(methodName, "ContextHandler element: " + element);
// If one of those possible elements has the AttributePrinciples
if (element.equals(ATTR_PRINCIPALS)) {
// Put the AttributesPrincipals into an ArrayList of CustomPrincipals
ArrayList<CustomPrincipal> customPrincipals =
(ArrayList<CustomPrincipal>) contextHandler.getValue(ATTR_PRINCIPALS);
int i = 0;
String attr;
if (customPrincipals != null) {
// For each AttributePrincipal in the ArrayList
for (CustomPrincipal customPrincipal : customPrincipals) {
// Get the Attribute Name and the Attribute Value
attr = customPrincipal.toString();
debug(methodName, "Attribute " + i + " Name: " + attr);
debug(methodName, "Attribute " + i + " Value: " + customPrincipal.getCollectionAsString());
// If the Attribute is "loginAccount"
if (attr.equals(ATTR_USERNAME)) {
user = customPrincipal.getCollectionAsString();
// Remove the "@DNS.DOMAIN.COM" (case insensitive) and set the username to that string
if (!user.equals("null")) {
user = user.replaceAll("(?i)\\@CLIENT\\.COMPANY\\.COM", "");
debug(methodName, "Username (from loginAccount): " + user);
break;
}
}
i++;
}
}
// For some reason the ArrayList of CustomPrincipals was blank - just set the username to the Subject
if (user == null || "".equals(user)) {
user = saml2NameMapperInfo.getName(); // Subject = BRID
debug(methodName, "Username (from Subject): " + user);
}
return user;
}
}
// Just in case AttributePrincipals does not exist
user = saml2NameMapperInfo.getName(); // Subject = BRID
debug(methodName, "Username (from Subject): " + user);
debugEnd(methodName);
// Set the username to the Subject
return user;
// debug(methodName,"com.bea.contextelement.saml.AttributePrincipals: " + arg1.getValue(ATTR_PRINCIPALS));
// debug(methodName,"com.bea.contextelement.saml.AttributePrincipals CLASS: " + arg1.getValue(ATTR_PRINCIPALS).getClass().getName());
// debug(methodName,"ArrayList toString: " + arr2.toString());
// debug(methodName,"Initial size of arr2: " + arr2.size());
}
//

/**
* Map Attribute Info to Collection<Principal>
* @param attrStmtInfos
* @param contextHandler
* @return
*/
public Collection<Principal> mapAttributeInfo(Collection<SAML2AttributeStatementInfo> attrStmtInfos,
ContextHandler contextHandler) {
final String methodName = className + ".mapAttributeInfo";
Collection<Principal> principals = null;
if (attrStmtInfos == null || attrStmtInfos.size() == 0) {
debug(methodName, "AttrStmtInfos has no elements");
} else {
principals = new ArrayList<Principal>();
for (SAML2AttributeStatementInfo stmtInfo : attrStmtInfos) {
Collection<SAML2AttributeInfo> attrs = stmtInfo.getAttributeInfo();
if (attrs == null || attrs.size() == 0) {
debug(methodName, "No attribute in statement: " + stmtInfo.toString());
} else {
for (SAML2AttributeInfo attr : attrs) {
CustomPrincipal principal = null;
String principalName = "";
Collection<String> attrValues = attr.getAttributeValues();
if (!attrValues.isEmpty()) {
int attrValIdx = 0;
for (String attrValue : attrValues) {
debug(methodName,
"Value " + ++attrValIdx + " of " + attr.getAttributeName() + "= " + attrValue);
if (attrValIdx == 1) {
principalName = attrValue;
}
}
} else {
principalName = attr.getAttributeName();
}
principal = new CustomPrincipal(principalName, attr.getAttributeValues());
debug(methodName, "Add principal: " + principal.toString());
principals.add(principal);
}
}
}
}
return principals;
}
//
private void debug(String methodName, String msg) {
lgr.fine(methodName + ": " + msg);
}
//
private void debugStart(String methodName) {
debug(methodName, "Start");
}
//
private void debugEnd(String methodName) {
debug(methodName, "End");
}

}

To be complete, here is the principal class:
package nl.darwinit.wls.saml;

import java.util.Collection;

import weblogic.security.principal.WLSAbstractPrincipal;
import weblogic.security.spi.WLSUser;


public class CustomPrincipal extends WLSAbstractPrincipal implements WLSUser {
@SuppressWarnings("compatibility:1303497257301553869")
private static final long serialVersionUID = 1L;

private String commonName;
private Collection<String> collection;

public CustomPrincipal(String name, Collection<String> collection) {
super();
// Feed the WLSAbstractPrincipal.name. Mandatory
this.setName(name);
this.setCommonName(name);
this.setCollection(collection);
}

public CustomPrincipal() {
super();
}

public CustomPrincipal(String commonName) {
super();
this.setName(commonName);
this.setCommonName(commonName);
}

public void setCommonName(String commonName) {
// Feed the WLSAbstractPrincipal.name. Mandatory
this.setName(commonName);
this.commonName = commonName;
System.out.println("Attribute: " + this.getName());
// System.out.println("Custom Principle commonName is " + this.commonName);
}

public Collection<String> getCollection() {
return collection;
}

public String getCollectionAsString() {
String collasstr = "null";
if (collection != null && collection.size() > 0) {
for (String value : collection) {
collasstr = value;
break;
}
/*for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
collasstr = (String) iterator.next();
return collasstr;
}*/
}
return collasstr;
}

public void setCollection(Collection<String> collection) {
this.collection = collection;
// System.out.println("set collection in CustomPrinciple!");
if (collection != null && collection.size() > 0) {
/*for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
final String value = (String) iterator.next();
System.out.println("Attribute Value: " + value);
}*/
for (String value : collection) {
System.out.println("Attribute Value: " + value);
}
}
}

@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((collection == null) ? 0 : collection.hashCode());
result = prime * result + ((commonName == null) ? 0 : commonName.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
CustomPrincipal other = (CustomPrincipal) obj;
if (collection == null) {
if (other.collection != null)
return false;
} else if (!collection.equals(other.collection))
return false;
if (commonName == null) {
if (other.commonName != null)
return false;
} else if (!commonName.equals(other.commonName))
return false;
return true;
}

}

In my earlier article I described how to add a reference to the jar file containing these classes to the java classpath field on the Server Start tab in the console.
In 12c this apparently does not work, the class is not picked up. Add it to the class path by creating/editing the setUserOverrides.sh/.cmd file.

Conclusion
This must be about it. We had quite a bit of Trial & Error. But most of the gotchas are listed here I think. But feel free to hire us if you need help. (Because I think you'll need the A-team for different issues...)

'No such file or directory' on starting your domain

Wed, 2017-04-26 05:30
Today I was triggered by this question. Earlier I had a similar problem, where I searched, and searched and searched and found the last section on this blogpost. Yes indeed, that is how it works when you blog: you might find your self finding your own blogposts again.

What is it about? Last year I wrote a nice set of scripts on installing Fusion Middleware and creating Fusion Middleware Weblogic domains.

I created the domain-creation-script based on scripts of Edwin Biemond, to get the credits straight.

However, in those scripts the  managed servers as wel as the admin server get Java Arguments set.

Those arguments refer to the logsHome property. I found that if you set JavaArgs you need to set redirects for weblogic.Stdout and weblogic.Stderr as well, 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. Or you could simply hash-out the lines:

#cd('ServerStart/'+server)
#print ('. Set Arguments to: '+javaArgs)
#set('Arguments' , javaArgs)

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

New and improved (re-)start and stop scripts for Fusion MiddleWare.

Tue, 2017-04-18 08:06
Last year I created a set of start and stop scripts for Weblogic/Fusion MiddleWare. Although I was quite happy with them at the time, I found that there was quite a lot of duplicate code. And I think I could improve them by combining at least the wlst scripts into one, making it a lot better maintainable, but also opening up for restart functionality. And doing so make the scripts more generic. I took my (re-)start and stop script for OHS components as an example and came up with an improved set of start/stop scripts.

For the property files (fmw12_env.sh, fmw.properties, user key files, etc. ) I refer to  start and stop scripts for Weblogic/Fusion MiddleWare.


WLSTAs said I created just one wlst script, startStopDomain.py:
#############################################################################
# Start, Stop, Restart FMW Domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.1, 2017-04-20
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = sys.argv[0]
#
#
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:7001"
print "adminUser=weblogic"
print "adminPwd=welcome1"
#
#
def connectToNM():
try:
wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
print(lineSeperator)
print('Try to connect to the Node Manager')
try:
nmConnect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
except NameError, e:
print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
print('Try to connect to the NodeManager adminUser and adminPwd properties')
nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
print('Connected to the Node Mananger')
except WLSTException:
message='Apparently NodeManager not Started!'
print (message)
raise Exception(message)
#
# Start Admin Server
def startAdminServer(adminServerName):
# Set wlsDomainHome
print ('Connect to the Node Manager')
connectToNM()
print('Start AdminServer')
nmStart(adminServerName)
#
# Connect To the AdminServer
def connectToAdminServer(adminUrl, adminServerName):
try:
print(lineSeperator)
print('Try to connect to the AdminServer')
try:
connect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, url=adminUrl)
except NameError, e:
print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
print('Try to connect to the AdminServer adminUser and adminPwd properties')
connect(adminUser, adminPwd, adminUrl)
except WLSTException:
print('Apparently AdminServer not Started!')
startAdminServer(adminServerName)
print('Retry to connect to the AdminServer')
try:
connect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, url=adminUrl)
except NameError, e:
print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
print('Try to connect to the AdminServer adminUser and adminPwd properties')
connect(adminUser, adminPwd, adminUrl)
#
# Get the Name of the AdminServer of Domain
def getAdminServerName():
serverConfig()
cd('/')
adminServerName=cmo.getAdminServerName()
return adminServerName
#
# Get the Servers of Domain
def getDomainServers():
print(lineSeperator)
print('\nGet Servers from domain')
serverConfig()
cd("/")
servers = cmo.getServers()
return servers
#
# Get the Servers of Cluster
def getClusterServers(clustername):
#Cluster config to be fetched from ServerConfig
print(lineSeperator)
print('\nGet Servers from cluster '+clustername)
serverConfig()
cluster = getMBean("/Clusters/" + clustername)
if cluster is None:
errorMsg= "Cluster " + clustername + " does not appear to exist!"
print errorMsg
raise(Exception(errorMsg))
print "Found cluster "+ clustername+ "."
servers = cluster.getServers()
return servers
#
# Get the Domain Clusters
def getClusters():
#Cluster config to be fetched from ServerConfig
print(lineSeperator)
print('\nGet Clusters')
cd('/')
clusters = cmo.getClusters()
return clusters
#
# Get status of a server
def serverStatus(serverName):
serverRuntime=getMBean('/ServerRuntimes/'+serverName)
if serverRuntime is None:
print("Server Runtime for " + serverName + " not found, server apparently SHUTDOWN")
serverState="SHUTDOWN"
else:
print "Found Server Runtime for "+ serverName+ "."
serverState = serverRuntime.getState()
return serverState
#
# Start Server
# Expected to be in domainRuntime to get to the serverRuntimes.
def startMServer(serverName):
print(lineSeperator)
print('ServerName: '+serverName)
serverState = serverStatus(serverName)
print('Server '+serverName+': '+serverState)
if serverState=="SHUTDOWN":
print ('Server '+serverName+' is not running so start it.')
start(serverName,'Server')
elif serverState=="RUNNING":
print ('Server '+serverName+' is already running')
else:
print ('Server '+serverName+' in state '+serverState+', not startable!')
#
# Start servers in a cluster one by one.
def startMServers(serverList):
print(lineSeperator)
print ('Start servers from list: '+serverList)
servers=serverList.split(',')
# Need to go to domainRuntime to get to the serverRuntimes.
domainRuntime()
#
for serverName in servers:
startMServer(serverName)
#
print ('\nFinished starting servers.')
#
# Start servers in a cluster one by one.
def startClusterServers(clusterName):
print(lineSeperator)
print ('Start servers for cluster: '+clusterName)
servers=getClusterServers(clusterName)
# Need to go to domainRuntime to get to the serverRuntimes.
domainRuntime()
#
for server in servers:
serverName = server.getName()
startMServer(serverName)
#
print ('\nFinished starting servers.')
#
# Start servers in domain one by one.
def startDomainServers():
print(lineSeperator)
print ('Start servers for domain')
servers=getDomainServers()
adminServerName=getAdminServerName()
# Need to go to domainRuntime to get to the serverRuntimes.
domainRuntime()
#
for server in servers:
serverName = server.getName()
if (serverName!=adminServerName):
startMServer(serverName)
else:
print('Skip '+adminServerName)
#
print ('\nFinished starting servers.')
#
# Stop Server
# Expected to be in domainRuntime to get to the serverRuntimes.
def stopMServer(serverName):
print(lineSeperator)
print('ServerName: '+serverName)
serverState = serverStatus(serverName)
print('Server '+serverName+': '+serverState)
if serverState=="RUNNING":
print ('Server '+serverName+' is running so shut it down.')
shutdown(name=serverName, entityType='Server', force='true')
elif serverState=="SHUTDOWN":
print ('Server '+serverName+' is already down.')
else:
print ('Server '+serverName+' in state '+serverState+', but try to stop it!')
shutdown(name=serverName, entityType='Server', force='true')
#
# Stop servers in a list
def stopMServers(serverList):
print(lineSeperator)
print ('Stop servers from list: '+serverList)
servers=serverList.split(',')
# Need to go to domainRuntime to get to the serverRuntimes.
domainRuntime()
#
for serverName in servers:
stopMServer(serverName)
#
print ('\nFinished stopping servers.')
#
# Stop servers in a cluster one by one.
def stopClusterServers(clusterName):
print(lineSeperator)
print ('Stop servers for cluster: '+clusterName)
servers=getClusterServers(clusterName)
# Need to go to domainRuntime to get to the serverRuntimes.
domainRuntime()
#
for server in servers:
serverName = server.getName()
stopMServer(serverName)
#
print ('\nFinished stopping servers.')
#
# Stop servers in a domain one by one.
def stopDomainServers():
print(lineSeperator)
print ('Stop servers for domain')
servers=getDomainServers()
adminServerName=getAdminServerName()
# Need to go to domainRuntime to get to the serverRuntimes.
domainRuntime()
#
for server in servers:
serverName = server.getName()
if (serverName!=adminServerName):
stopMServer(serverName)
else:
print('Skip '+adminServerName)
#
print ('\nFinished stopping servers.')
#
# Start cluster
def startCluster(clusterName):
print(lineSeperator)
print ('Start cluster: '+clusterName)
try:
start(clusterName,'Cluster')
except WLSTException:
print "Apparently Cluster in incompatible state!", sys.exc_info()[0], sys.exc_info()[1]
startClusterServers(clusterName)
state(clusterName,'Cluster')
#
print ('\nFinished starting cluster '+clusterName)
#
# Start clusters in a list
def startClusters(clusterList):
print(lineSeperator)
print ('Start clusters from list: '+clusterList)
clusters=clusterList.split(',')
#
for clusterName in clusters:
startCluster(clusterName)
#
print ('\nFinished starting clusters.')
#
# Start clusters
def startDomainClusters():
print(lineSeperator)
print ('Start clusters')
clusters=getClusters()
#
for cluster in clusters:
clusterName = cluster.getName()
startCluster(clusterName)
#
print ('\nFinished starting clusters.')
#
# Stop cluster
def stopCluster(clusterName):
print(lineSeperator)
print ('Stop cluster: '+clusterName)
try:
#shutdown(clusterName,'Cluster')
shutdown(name=serverName, entityType='Cluster', force='true')
state(clusterName,'Cluster')
except WLSTException:
print "Apparently Cluster in incompatible state!", sys.exc_info()[0], sys.exc_info()[1]
state(clusterName,'Cluster')
print ('Try to stop servers for cluster: '+clusterName+', one by one')
stopClusterServers(clusterName)
#
print ('\nFinished stopping cluster '+clusterName)
#
# Stop clusters in a list
def stopClusters(clusterList):
print(lineSeperator)
print ('Stop clusters from list: '+clusterList)
clusters=clusterList.split(',')
#
for clusterName in clusters:
stopCluster(clusterName)
#
print ('\nFinished stopping clusters.')
#
# Stop all clusters of the domain
def stopDomainClusters():
print(lineSeperator)
print ('Stop clusters')
clusters=getClusters()
#
for cluster in clusters:
clusterName = cluster.getName()
stopCluster(clusterName)
#
print ('\nFinished stopping clusters.')
#
# StopAdmin
def stopAdmin():
print(lineSeperator)
print('Stop '+adminServerName)
shutdown(force='true')
serverState = serverStatus(serverName)
print('State '+adminServerName+': '+ serverState)
print('\nFinished stopping AdminServer: '+adminServerName)
#
# Start admin Server
def startAdmin():
print(lineSeperator)
print('Start and connect to '+adminServerName)
connectToAdminServer(adminUrl, adminServerName)
print('\nFinished starting AdminServer: '+adminServerName)
#
# Stop a domain
def stopDomain():
print (lineSeperator)
stopDomainClusters()
#
stopAdmin()
print ('\nFinished stopping domain.')
#
#
# Start a Domain
def startDomain():
print (lineSeperator)
#
startAdmin()
#
startDomainClusters()
#
print ('\nFinished starting domain.')
#
#
# (Re-)Start or Stop Domain
def startStopDomain(startStopOption):
if startStopOption=="stop" or startStopOption=="restart":
stopDomain()
if startStopOption=="start" or startStopOption=="restart":
startDomain()
#
# (Re-)Start or Stop Admin
def startStopAdmin(startStopOption):
if startStopOption=="stop" or startStopOption=="restart":
stopAdmin()
if startStopOption=="start" or startStopOption=="restart":
startAdmin()
#
# (Re-)Start or Stop Clusters
def startStopClusters(startStopOption, clusterList):
if startStopOption=="stop" or startStopOption=="restart":
if clusterList is None:
stopDomainClusters()
else:
stopClusters(clusterList)
if startStopOption=="start" or startStopOption=="restart":
if clusterList is None:
startDomainClusters()
else:
startClusters(clusterList)
#
# (Re-)Start or Stop Servers
def startStopServers(startStopOption, serverList):
if startStopOption=="stop" or startStopOption=="restart":
if serverList is None:
stopDomainServers()
else:
stopMServers(serverList)
if startStopOption=="start" or startStopOption=="restart":
if serverList is None:
startDomainServers()
else:
startMServers(serverList)
#
# Main
def main():
try:
print ('Args passed: '+ str(len(sys.argv) ))
componentList = None
idx = 0
for arg in sys.argv:
if idx == 0:
print 'ScriptName: '+arg
elif idx == 1:
# startStopOption: start, stop, restart
startStopOption=arg
elif idx == 2:
# componentType: AdminSvr, Domain, Clusters, Servers
componentType=arg
elif idx == 3:
componentList=arg
else:
componentList = componentList+','+arg
idx=idx+1
#
#componentName=sys.argv[3]
# Set wlsDomainHome
wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
#
print(lineSeperator)
if componentList is None:
componentStr = componentType
else:
componentStr = componentType+' '+componentList
if startStopOption=="start" or startStopOption=="restart":
print('(Re)Start '+componentStr+' in '+wlsDomainHome+', with option '+startStopOption)
elif startStopOption=="stop":
print('Stop '+componentStr+' in '+wlsDomainHome+', with option '+startStopOption)
else:
raise Exception("Unkown startStopOption: "+ startStopOption)
#
print(lineSeperator)
print('\nConnect to the AdminServer: '+adminServerName)
connectToAdminServer(adminUrl, adminServerName)
#
print('Connected, so proceed with: '+startStopOption+' of '+componentType)
#
if componentType=="AdminSvr":
startStopAdmin(startStopOption)
elif componentType=="Domain":
startStopDomain(startStopOption)
elif componentType=="Clusters":
startStopClusters(startStopOption, componentList)
elif componentType=="Servers":
startStopServers(startStopOption, componentList)
else:
raise Exception('Undefined componentType: '+componentType);
#
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())
exit(exitcode=1)
#call main()
main()
exit()

The script can be called with two parameters and a property file:

  • startStopOption: start, stop, restart
  • component: AdminSvr, Domain, Clusters, Servers
Based on the value of component the start, stop or restart option is issued on either the AdminServer, the Domain clusters, servers or the complete domain. The main function starts with connecting to the AdminServer. If the AdminServer is not started yet, it will connect to the NodeManager to start the AdminServer.

In case of a restart or a stop the particular components are stopped. And in case of a start or restart the particular components are started. 

The advancement of this script, in contrast with other start/stop scripts I've seen is that it will give a start command to a cluster. Doing so, all the servers in a cluster will get a start command simultaneously. For stopping the server in a cluster, the WLSException that can be raised in the stop command is caught, to try to stop try to stop the servers one by one. 

Another advancement of this script is that is determined which clusters there are in a domain, and these are traversed one by one.

Update 2017-04-20: Today I added also the possiblilty to start a list of clusters or servers. If you don't provide a list of clusters or servers, all the clusters or servers in the domain are (re-)started or stopped. Except for the AdminServer, by the way.

Bash
To call the wlst script I created a set of bash scripts.

To start the AdminServer, startAdmin.sh:
#!/bin/bash
#############################################################################
# Start AdminServer using wlst and connect to it.
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.2, 2016-04-18
#
#############################################################################
#
. fmw12c_env.sh
echo
echo Start AdminServer
wlst.sh ./startStopDomain.py start AdminSvr -loadProperties fmw.properties

To stop or restart the AdminServer, replace start in 'wlst.sh ./startStopDomain.py start AdminSvr' by either stop or restart. And save the file to either stopAdmin.sh or restartAdmin.sh.

To create the corresponding files for Domain or Clusters replace AdminSvr in the same line with either Domains or Clusters.

I think you'll get the drift. And of course you should adapt the comments and echo's.

But maybe a more generic (re-)start or stop script is startStopDmn.sh:

#!/bin/bash
#############################################################################
# Start Domain components using wlst
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2017-04-19
#
#############################################################################
#
. fmw12c_env.sh
export START_STOP_OPTION=$1
export COMPONENT_TYPE=$2
export ENV=$3
export COMPONENT_NAME=$4
echo
echo "(Re-)Start or stop Domain components"
wlst.sh ./startStopDomain.py ${START_STOP_OPTION} ${COMPONENT_TYPE} "${COMPONENT_NAME}" -loadProperties ${ENV}.properties

Then you could do a startAdmin.sh like:
./startStopDmn.sh start AdminSvr fmw

And a stopAdmin.sh like:
./startStopDmn.sh stop AdminSvr fmw

Or a restartServers.sh like:
./startStopDmn.sh restart Servers fmw $1

Here you can provide a comma-separated list of servers, between double-quotes:
./restartServers "soa_server1,soa_server2"
etc. etc.
Advantage of this approach is that it allows you to use the same script set for multiple environemts, by duplicating and adapting the fmw.properties file to other environments (like domains).

BPM BAC Subversion Server refusing connections

Thu, 2017-04-06 05:20
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.


Back from PaaSForum

Tue, 2017-04-04 09:32
So, and now we're back in business after a splendid week in Split, Croatia, to meet with about 200 great, enthusiastic con-colleagues from the fields of SOA and Weblogic. It was the yearly OPN Partner Community Forum, ran by the great Jürgen Kress. He did a formidable job to collect many informatic sessions on the latest news and products from Oracle. We could meet with product managers, eat  and drink with them. To my surprise I could shake hands with a Product Manager of PCS, with whom I worked closely on a try-out project at the end of last year.

It was at a great venu, Le Meridien, a short drive out side of Split. A nice hotel with fantastic views on the Adriatic Sea.

Last year on the 'OFM Forum' in Valencia, PaaS (Platform as a Service) as a 'MiddleWare Cloud' was an important subject. Oracle was heavily promoting  Cloud. This is why you could expect that this years forum was named 'PaaSForum'. And thus in one of the keynotes this was stressed by stating:


Now, our Dutch comedian Arjan Lubach made a video to introduce our country to president Trump:

So that made me introducing the statement:
I understand cloud 1st, but can Netherlands be 2nd? #PaaSForum pic.twitter.com/SMh4JX2zgs
— Makker (@Makker_nl) March 29, 2017 Fun aside, I heard many nice things. To sum up a view:

  • On ICS side, there would be a REPL CLI script to move iar's (ICS Archives) between environments, created by the A-Team. I should look it up, but don't know if it already released it.
  • There was an introduction of the API platform, with also a workshop on it.
  • PCS and ICS are suggested to be combined into the Integration Cloud. Which would be a very logical idea, bringing much better, uniformed user experience. Because, at my latest cloud project, last year, we actually defined the practice to always integrate via ICS not directly from PCS.
  • There would also be a script, created by a Product Manager, to 'massage' BPM projects to transform them into a PCS compliant project. Hope to get my hands on that too, that could certainly be helpful. The otherway around would be not so bad either.
  • Then there was the mention of AI Apps, or Application Intelligent apps. Intelligence from verticals. This could drive PCS in a more intelligent way, based on knowledge from different verticals. 
  • New DMN Decision service in #PCS . Got to check that out soon. #PaaS4SaaS, #PaaSForum . pic.twitter.com/PadknKyH9R
    — Makker (@Makker_nl) March 31, 2017
But most interesting I found was the introduction of CMMN in PCS. Or otherwise put: Dynamic Processes in PCS. Where conventional BPMN processes in PCS run in a strict predefined way, with Dynamic Processes Case Management capabilities are introduced in PCS. Much like Adaptive Case Management in BPM Suite. However, build in a new way with a graphical modeller in the composer:

So here you see vertical lanes that represent phases in the process. In each phase you can define activities that can represent a Human Task, or for instance, a (sub-)process:
Activities can be repeatable, required or Manually Activated. Much like we can do in ACM.

Then using Decision rules you can decide under which condition the case is transferred to another phase, activities are activated or deactivated, etc. Or this can be done by the knowledge-worker self.


So I'm very much looking forward to get my fingers on this new functionality.

Another interesting new development is the introduction of Chat bots. They were so heavily mentioned and demoed, there hardly weren't any presentations without mentioning them. I almost felt I was one of the few that liked them, although the heavily relying on Facebook messenger. Even the, in my perception, breeding ground of chat bots, Twitter, wasn't free of criticism on the usecase of chatbots. I, on the other hand found a great non-functional use of chatbots: a text based adventure:

If we could combine PCS's dynamic processes with the Oracle Chat bot cloud service, we could develop a nice text adventure where you could chase beacons with in the process. Each phase in the process could represent a location, different processes can represent several areas on the map. But if we can have the process instances interact with eachother, for instance by registering their locations in a DBCS, or sending correlated signals (much nicer), then you could make it into a multiplayer text adventure. My colleague Rob introduced the idea to be able to upload pictures, of real-life locations. You could readout the Exif-data to check if the foto really represent a GPS-location.

So, that might be the next rolling-gag or app on the next forum in 2018, for which I already introduced the hash-tag: #ChatBotForum. In the aftermath of the week, at Jürgens afterparty, one of the others also mentioned text adventures. So, apparently, it wasn't such a far-fetched idea.

There's so much to think about, have it land, and much is already said. I'm looking forward to see how it all works out in the next year. The sun died on the #PaaSForum'17:


Working up to #ChatBotForum'18...

Start, Restart and stop OHS Components

Tue, 2017-03-21 05:08
In Fusion Middleware 12c the Oracle HTTP Server is now configured as SystemComponents within a Weblogic Domain. This can be embedded in a FMW Domain, like SOA, OSB, or WebCenter.  Or it can be in a stand alone domain.

When configured, there are scripts to start and stop the system components in the bin folder of the domain: startComponent.sh and stopComponent.sh.

These scripts first do a readDomain() to read the domain before actually starting or stopping the component. An OHS Standalone Domain is not that large, but does take a few seconds. With an embedded OHS it can actually a quite expensive operation. And is done twice when you need to stop and start a component. And that per component.

So, this can be smarter. Yesterday, I created a script that first looks for a property in the property file, that lists the possible components as a comma seperated list. It only does a readDomain() when that property is not defined.

The property file ohs.properties contains:

#############################################################################
# Set OHS SA Domain properties
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2017-02-20
#
#############################################################################
#
#Per domain nodemanager...
nmHome=/u01/data/oracle/config/domains/ohs_domain/nodemanager
nmHost=localhost
nmPort=5555
nmType=plain
#
#Domain
wlsDomainName=ohs_domain
wlsDomainsHome=/u01/data/oracle/config/domains
#
#AdminServer
adminUser=weblogic
adminPwd=welcome1
#usrCfgFile=wlsCfgFile
#usrKeyFile=wlsKeyFile
#
# OHS Component List
ohsComponents=ohs1

The wlst script startStopOhs.py is:
#############################################################################
# Start OHS via NodeManager.
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 1.0, 2017-03-01
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = sys.argv[0]
#
#
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 connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType):
try:
print(lineSeperator)
print('Try to connect to the Node Manager')
nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
print('Connected to the Node Mananger')
except WLSTException:
message='Apparently NodeManager not Started!'
print (message)
raise Exception(message)
#
#
def getSystemComponents(wlsDomainHome):
try:
print(lineSeperator)
print('Get SystemComponents')
try:
sysComps=ohsComponents.split(',')
except NameError, e:
print 'Property ohsComponents not set, read from Domain'
print('Read domain from : '+wlsDomainHome)
readDomain(wlsDomainHome)
cd('/SystemComponent')
sysComps=ls(returnMap='true')
return sysComps
except WLSTException:
message='Exception getting SystemComponents'
print (message)
raise Exception(message)
#
# Start a System Component
def startSystemComponent(sysComp):
try:
print(lineSeperator)
print('StartSystemComponent '+sysComp)
nmStart(serverName=sysComp, serverType='OHS')
except WLSTException:
message='Exception starting SystemComponent: '+sysComp
print (message)
raise Exception(message)
#
# Stop a System Component
def stopSystemComponent(sysComp):
try:
print(lineSeperator)
print('StartSystemComponent '+sysComp)
nmKill(serverName=sysComp, serverType='OHS')
except WLSTException:
message='Exception stopping SystemComponent: '+sysComp
print (message)
raise Exception(message)
#
# Start, restart or stop System Components, based on startStopOption.
def startStopSystemComponents(startStopOption, sysComps):
try:
print(lineSeperator)
print('StartSystemComponents')
if startStopOption=="stop" or startStopOption=="restart":
for sysComp in sysComps:
stopSystemComponent(sysComp)
if startStopOption=="start" or startStopOption=="restart":
for sysComp in sysComps:
startSystemComponent(sysComp)
except WLSTException:
message='Exception starting or stopping SystemComponents, startStopOption:'+startStopOption
print (message)
raise Exception(message)
#
#
def main():
try:
startStopOption=sys.argv[1]
wlsDomainHome = wlsDomainsHome+'/'+wlsDomainName
print(lineSeperator)
if startStopOption=="start" or startStopOption=="restart":
print('(Re)Start OHS for domain in : '+wlsDomainHome+', with option '+startStopOption)
else:
print('Stop OHS for domain in : '+wlsDomainHome+', with option '+startStopOption)
print(lineSeperator)
print ('Connect to the Node Manager')
connectToNM(nmHost, nmPort, nmHome, wlsDomainName, wlsDomainHome, nmType)
#
systemComponents=getSystemComponents(wlsDomainHome)
#
startStopSystemComponents(startStopOption, systemComponents)

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())
exit(exitcode=1)
#
main();

It uses a startStopOption that can have the values:

  • start
  • restart
  • stop
Based on that, it determines if the components need to be stopped, and/or, started again.

So, this time I only have one wlst script. I could make my weblogic server start scripts smarter the same way...

To start the ohs you can use startOhs.sh:
#!/bin/bash
. ./ohs12c_env.sh
echo
echo Start OHS
wlst.sh ./startStopOhs.py start -loadProperties ohs.properties

To restart the ohs you can use restartOhs.sh:
#!/bin/bash
. ./ohs12c_env.sh
echo
echo Restart OHS
wlst.sh ./startStopOhs.py restart -loadProperties ohs.properties

And to stop the ohs you can use stopOhs.sh:
#!/bin/bash
. ./ohs12c_env.sh
echo
echo Stop OHS
wlst.sh ./startStopOhs.py stop -loadProperties ohs.properties

With a OHS Standalone domain, you probably have stored the nodemanager credentials once with the storeConfig option. In that case you can remove the credentials in the nmConnnect line:

#nmConnect(username=adminUser, password=adminPwd, host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)
nmConnect(host=nmHost, port=nmPort, domainName=wlsDomainName, domainDir=wlsDomainHome, nmType=nmType)

For a standalone OHS the ohs12c_env.sh script contains:
#!/bin/bash
echo set OHS StandAlone 12cR2 environment
#export JAVA_HOME=/usr/java/jdk1.8.0_101
#export ORACLE_BASE=/app/oracle
export ORACLE_BASE=/u01/app/oracle
export OHS_HOME=$ORACLE_BASE/product/middleware/OHS12212
export WL_HOME=${OHS_HOME}/wlserver
export SHARED_CONFIG_DIR=/u01/data/oracle/config
export OHS_DOMAIN_NAME=ohs_domain
export OHS_DOMAIN_HOME=$SHARED_CONFIG_DIR/domains/$OHS_DOMAIN_NAME
export NODEMGR_HOME=$OHS_DOMAIN_HOME/nodemanager
#
echo Set Weblogic Common Env.
. $OHS_HOME/oracle_common/common/bin/commEnv.sh
#
export PATH=$OHS_HOME/oracle_common/common/bin:$PATH


Install and configure Oracle HTTP Server Standalone

Thu, 2017-02-16 09:30
Last week I had an assignment to install and configure Oracle HTTP Server as a reversed proxy in a DMZ. Many years ago I worked with Apache a little, so I had not have the details at hand.

Although installing and configuring the HTTP Server is not hard, I found that I had to do quite some searching around to get to all the essentials. To help you out, and to have it logged for myself, let's get through it.

Install OHS Software
For installing the OHS Software I created a script as I did for other FMW installations (FMW Infrastructure, OSB, SOA/BPM, etc.). I did my installation on a Oracle Linux 7 VM, that already contained the database and Weblogic. So I did not need to add the necessary packages. See for instance the requirements doc.

The script starts with the following settings:

Variable
Meaning
Suggested Value (12.2.1.2)OHS_ZIP_HOMELocation of the Zip file(s) of the installation. $PWD/../Zipped/OHSOHS_INSTALL_HOMELocation to extract the Zip file(s) of the installation to.$PWD/../Extracted/stage/OHSOHS_INSTALL_BINName of the installer within the Zip file(s)fmw_12.2.1.2.0_ohs_linux64.binOHSSA_INSTALL_RSPName of the response file to use in the installerfmw_12.2.1.2.0_ohs_sa.rspOHSSA_INSTALL_RSP_TPLName of the response file template, to expand to the actual response file.$OHSSA_INSTALL_RSP.tplOHS_INSTALL_ZIPName of the zip file that contains the installer.V789368-01.zip
As in earlier blogs I use a fmw12c_env.sh script to set variables to point to the locations/homes of the software. For this script I need the following variables (so add them if not present):
Variable
Meaning
Suggested Value (12.2.1.2)ORACLE_BASEBase location of the oracle installations/u01/app/oracle or /app/oracleOHSSA_HOMEHome for the installation of a StandAlone OHS.$ORACLE_BASE/product/middleware/OHS12212

The script installOHS_SA.sh is as follows:

#!/bin/bash
. $PWD/fmw12c_env.sh
#
export OHS_ZIP_HOME=$PWD/../Zipped/OHS
export OHS_INSTALL_HOME=$PWD/../Extracted/stage/OHS
export OHS_INSTALL_BIN=fmw_12.2.1.2.0_ohs_linux64.bin
export OHSSA_INSTALL_RSP=fmw_12.2.1.2.0_ohs_sa.rsp
export OHSSA_INSTALL_RSP_TPL=$OHSSA_INSTALL_RSP.tpl
export OHS_INSTALL_ZIP=V789368-01.zip
#
# Oracle Webtier 12c
if [ ! -d "$OHSSA_HOME" ]; then
#
#Unzip OHS Software
if [ ! -f "$OHS_INSTALL_HOME/$OHS_INSTALL_BIN" ]; then
if [ -f "$OHS_ZIP_HOME/$OHS_INSTALL_ZIP" ]; then
if [ ! -d "$OHS_INSTALL_HOME" ]; then
echo Create folder "$OHS_INSTALL_HOME"
mkdir -p "$OHS_INSTALL_HOME"
fi
echo Unzip $OHS_ZIP_HOME/$OHS_INSTALL_ZIP to $OHS_INSTALL_HOME/$OHS_INSTALL_BIN
unzip -o $OHS_ZIP_HOME/$OHS_INSTALL_ZIP -d $OHS_INSTALL_HOME
else
echo $OHS_INSTALL_HOME/$OHS_INSTALL_ZIP does not exist!
fi
else
echo $OHS_INSTALL_BIN already unzipped
fi
if [ -f "$OHS_INSTALL_HOME/$OHS_INSTALL_BIN" ]; then
echo Substitute $OHSSA_INSTALL_RSP_TPL to $OHSSA_INSTALL_RSP
envsubst < $OHSSA_INSTALL_RSP_TPL > $OHSSA_INSTALL_RSP
echo Install Oracle HTTP Server 12cR2 StandAlone
$OHS_INSTALL_HOME/$OHS_INSTALL_BIN -silent -responseFile $PWD/$OHSSA_INSTALL_RSP
else
echo $OHS_INSTALL_BIN not available!
fi
else
echo $OHSSA_HOME available: WebTier installed
fi

The script checks if the OHS Home already exists, if so it concludes that the software apparently is installed already. If not, it checks if the installer is available, and if that is not the case it checks if the zip is available. It will unzip the installer if needed and if one of the checks fail it will stop.

A new thing I found out after my earlier blogs is that I learned about the envsubst command that is available in Oracle Linux. It enables you to expand the environment variables that occur in a file. And for this script this is handy, because it needs a response file for the installer, but that contains for instance an Oracle Home to be set to the target $OHSSA_HOME from the fmw12c_env.sh script. In my earlier scripts, when I needed or wanted to install using other folder structures I needed to change both the script and the response file. Now I used the response file saved from the manual installation and then replaced the folder with the particular environment variable.

The response file template, I called fmw_12.2.1.2.0_ohs_sa.rsp.tpl, looks like:
[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=${OHSSA_HOME}

#Set this variable value to the Installation Type selected as either Standalone HTTP Server (Managed independently of WebLogic server) OR Collocated HTTP Server (Managed through WebLogic server)
INSTALL_TYPE=Standalone HTTP Server (Managed independently of WebLogic server)

#Provide the My Oracle Support Username. If you wish to ignore Oracle Configuration Manager configuration provide empty string for user name.
MYORACLESUPPORT_USERNAME=

#Provide the My Oracle Support Password
MYORACLESUPPORT_PASSWORD=<SECURE VALUE>

#Set this to true if you wish to decline the security updates. Setting this to true and providing empty string for My Oracle Support username will ignore the Oracle Configuration Manager configuration
DECLINE_SECURITY_UPDATES=true

#Set this to true if My Oracle Support Password is specified
SECURITY_UPDATES_VIA_MYORACLESUPPORT=false

#Provide the Proxy Host
PROXY_HOST=

#Provide the Proxy Port
PROXY_PORT=

#Provide the Proxy Username
PROXY_USER=

#Provide the Proxy Password
PROXY_PWD=<SECURE VALUE>

#Type String (URL format) Indicates the OCM Repeater URL which should be of the format [scheme[Http/Https]]://[repeater host]:[repeater port]
COLLECTOR_SUPPORTHUB_URL=


Create a folder structure, place the scripts fmw12c_env.sh, installOHS_SA.sh and fmw_12.2.1.2.0_ohs_sa.rsp.tpl  in a folder named scripts. Then create a folder named Zipped/OHS next to it. Download the OHS installer from edelivery.oracle.com and save it in that folder.
Also create an empty folder named Extracted/stage/OHS next to it. Then run the installOHS_SA.sh.


Configure the DomainUnfortunately it is apparently not possible to create the domain  with a wlst script. Main reason for this (I think) is that the wlst installation in the OHS FMW_home lacks an implementation of the encrypt() method to encrypt a password against the SA-domain folder. Therefor you can't set the (encrypted) domain password and nodemanager password. And thus you can't start the OHS components in the regular way using the nodemanager.

So configuring the domain is done manually using the configurator.
Start the config.sh vanuit $OHS_HOME/oracle_common/common/bin:
[oracle@darlin-vce-db scripts]$ cd /u01/app/oracle/product/middleware/OHS12212/oracle_common/common/bin

[oracle@darlin-vce-db bin]$ ls

cam_clonedunpack.sh cam_wlst.sh config.sh setHomeDirs.sh

cam_config.sh clonedunpack.sh configWallet.sh unpack.sh

cam_pack.sh commBaseEnv.sh getproperty.sh wlst.sh

cam_reconfig.sh commEnv.sh pack.sh

cam_unpack.sh commExtEnv.sh reconfig.sh

[oracle@darlin-vce-db bin]$ ./config.sh


Provide a domain home like: /u01/app/work/domains/ohs_domain.
Check the Oracle HTTP Server (Standalone) option.
The documentation suggest to select the Oracle Hotspot JDK, delivered with the installation.
Here you can add system components to the domain.
Per system component provide the listen address and port, as well as the Admin Host and Port.
Let's keep the defaults.
Keep the ‘Per Domain Default location’ option.
From Weblogic 12c this is the standard.
Keep the username weblogicand provide a password. For demo purposes I use the password welcome1.

Actually this is the step I couldn't manage to do with WLST.
Validate the settings.
The progress of the creation of the domain.
Confirm the configuration of the domain.Further configuration of OHSYou'll need to add routes. For the plain http routes you can add a configuration file, like service_vh.conf (where service is the name of the application or purpose for which you want to use OHS). In my case I was routing an APEX application through ORDS, so I named it ords_vh.conf.
An example of the file is:
<VirtualHost *:7777>
ServerName admin.darlin-vce-db:7777
ServerAdmin martien.van.den.akker@darwin-it.nl
RewriteEngine On
RewriteOptions inherit
# Admin Server and EM
<Location /console>
WLSRequest ON
WebLogicHost darlin-vce-db
WeblogicPort 7001
</Location>
<Location /consolehelp>
WLSRequest ON
WebLogicHost darlin-vce-db
WeblogicPort 7001
</Location>
<Location /em>
WLSRequest ON
WebLogicHost darlin-vce-db
WeblogicPort 7001
</Location>
# APEX in Admin Server
<Location /ords>
WLSRequest ON
WebLogicHost darlin-vce-db
WeblogicPort 7001
</Location>
<Location /ords/apex_admin>
WLSRequest ON
WebLogicHost darlin-vce-db
WeblogicPort 7001
</Location>
<Location /i>
WLSRequest ON
WebLogicHost darlin-vce-db
WeblogicPort 7001
</Location>
</VirtualHost>

Place this file the folder $OHS_DOMAIN_HOME/config/fmwconfig/components/OHS/ohs1/moduleconf. All files with extension ‘.conf’ in this folder are picked up automatically by the OHS component.
Start OHSAdapt Nodemanager
Change the nodemanager.properties in $OHS_DOMAIN/nodemanager/nodemanager.properties:
#Node manager properties
#Tue Jan 24 14:41:26 CET 2017
DomainsFile=/u01/app/work/domains/ohs_domain/nodemanager/nodemanager.domains
LogLimit=0
PropertiesVersion=12.2.1
AuthenticationEnabled=true
NodeManagerHome=/u01/app/work/domains/ohs_domain/nodemanager
JavaHome=/usr/java/jdk1.8.0_74
LogLevel=INFO
DomainsFileEnabled=true
ListenAddress=localhost
NativeVersionEnabled=true
#ListenPort=5556
ListenPort=7555
LogToStderr=true
weblogic.StartScriptName=startWebLogic.sh
#SecureListener=true
SecureListener=false
LogCount=1
QuitEnabled=false
LogAppend=true
weblogic.StopScriptEnabled=false
StateCheckInterval=500
CrashRecoveryEnabled=false
weblogic.StartScriptEnabled=true
LogFile=/u01/app/work/domains/ohs_domain/nodemanager/nodemanager.log
LogFormatter=weblogic.nodemanager.server.LogFormatter
ListenBacklog=50


In this file change the following properties:
  • SecureListener=false
  • ListenPort=5555

If you already have a nodemanager running, possibly for another domain (not likely when using this in a DMZ) you can use another port. For instance 7555.
As a good practice I tend to duplicate the lines, comment out the original ones and change the duplicates.
Because we changed the nodemanager config, we need to update the domain. This can be done by a wlst file like the following setNodeManagerListenPort.py:
readDomain('/u01/app/work/domains/ohs_domain')
cd ('Machine/localmachine/NodeManager/localmachine')
set('ListenPort',7555)
set('NMType','plain')
updateDomain()

That can be run as:
[oracle@darlin-vce-db OHSSaDomain]$ . ./ohs12c_env.sh
set OHS StandAlone 12cR2 environment
Set Weblogic Common Env.
[oracle@darlin-vce-db OHSSaDomain]$ wlst.sh setNodeManagerListenPort.py


Here the content of the environment script ohs12c_env.sh is as follows:
#!/bin/bash
echo set OHS StandAlone 12cR2 environment
#export JAVA_HOME=/usr/java/jdk1.8.0_101
#export ORACLE_BASE=/app/oracle
export ORACLE_BASE=/u01/app/oracle
export OHS_HOME=$ORACLE_BASE/product/middleware/OHS12212
export WL_HOME=${OHS_HOME}/wlserver
export SHARED_CONFIG_DIR=/u01/app/work
export OHS_DOMAIN_NAME=ohs_domain
export OHS_DOMAIN_HOME=$SHARED_CONFIG_DIR/domains/$OHS_DOMAIN_NAME
export NODEMGR_HOME=$OHS_DOMAIN_HOME/nodemanager
#
echo Set Weblogic Common Env.
. $OHS_HOME/oracle_common/common/bin/commEnv.sh
#
export PATH=$OHS_HOME/oracle_common/common/bin:$PATH

Start NodemanagerYou can start the nodemanager using $DOMAIN_HOME/bin/startNodemanager.sh. It can also using a custom script like:

#!/bin/bash
. ohs12c_env.sh
echo Start NodeManager
nohup $OHS_DOMAIN_HOME/bin/startNodeManager.sh > $OHS_DOMAIN_HOME/nodemanager/nm.out&

This starts the nodemanager in the background.
Start OHS
When you start OHS initially, you can do it like below, to store the userconfig:
[oracle@darlin-vce-db bin]$ ./startComponent.sh ohs1 storeUserConfig
Starting system Component ohs1 ...

Initializing WebLogic Scripting Tool (WLST) ...

Welcome to WebLogic Server Administration Scripting Shell

Type help() for help on available commands

Reading domain from /u01/app/work/domains/ohs_domain


Please enter Node Manager password:
Creating the key file can reduce the security of your system if it is not kept in a secured location after it is created. Creating new key...
The username and password that were used for this WebLogic NodeManager connection are stored in /home/oracle/.wlst/nm-cfg-ohs_domain.props and /home/oracle/.wlst/nm-key-ohs_domain.props.
Connecting to Node Manager ...
Successfully Connected to Node Manager.
Starting server ohs1 ...
Successfully started server ohs1 ...
Successfully disconnected from Node Manager.


Exiting WebLogic Scripting Tool.

Done
[oracle@darlin-vce-db bin]$

This starts the OHS and stores the password encrypted. Every following time, you can start it like:
#!/bin/bash
. ./ohs12c_env.sh
echo Stop Ohs1
$OHS_DOMAIN_HOME/bin/stopComponent.sh ohs1
echo Start Ohs1
$OHS_DOMAIN_HOME/bin/startComponent.sh ohs1


FinallyIn my case I had to configure SSL as well. This included creating a wallet with a certificate etc.
I'll save that for another article, because this one is already quite extensive.

Property expansion under windows.

Thu, 2017-01-12 08:00
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...

Recursion in XSLT

Thu, 2017-01-12 02:35
Yesterday I got involved in a question to handle a list of input documents where there is a start value and for every other element this start value has to be increased until an end value is reached.

In more advanced XSLT cases you may end up in a situations that aren't solvable using a for-each. Why not? Well, in the for-each you can't iteratively re-calculate a variable. Like a program language as Scala, XSLT is in fact a so called 'functional' language. Maybe not in the strict sense of the definition (I haven't checked), but one of the definitions is that in a functional language, or at least in Scala, variables are immutable. In XSLT once assigned a value, a variable cannot be changed. So a variable in XSLT is only variable at first assignment.

How to solve this? Well, with recursion. This morning I googled on XSLT and recursion and found this nice explanation.

Recursion is a paradigm in which a certain object or functionality is repeated by itself.

In computer programming this is done by defining a function with a specific implementation of functionality and where before of after that implementation the function calls itself with an altered set of input values until a certain end-condition is reached. It's one of the first computer algorithms I learned in a language as Pascal. And a typical example is calculating the factorial of a natural number.

I use recursion in XSLT regularly, for instance in a template that replaces a string in an another string until all occurrences have been replaced. I wrote about that in 2010 already.

In this blog post I'll omit providing an example, since I already provided a few in the articles linked above. I just want to draw your attention to this concept in XSLT. But if you like to read more on XSLT and recursion, you might be interested in this blog article.


Note to myself: when handling large payloads

Thu, 2016-12-01 07:36
Today I stumbled on a question in the communities about handling large payloads in BPEL/XSLT. Although I know that SOASuite from 11g onwards can do paging of XML to disk, I never had the need. However, you could need it from time to time. And it's good to know how to do it.

It's noted on My Oracle Support with Doc ID 1327970.1. Which refers to the 11g documentation on Managing Large Documents and Large Numbers of Instances.

Learning all the time....


XMind 8 is published

Wed, 2016-11-02 06:16
Already several years I´m a user of XMind. It is a very rich free MindMapping tool. I find the free version very usefull.

Today I found out that the new XMind 8 is published. You can get it on xmind.net.

Enjoy.

OSB Thread handling recommendations

Mon, 2016-10-31 02:29
I have got questions on performance of OSB quite a few times already, during the years. A few years ago on a project I got eyes on a set of recommendations on workmanagers for OSB. Many developers know that for instance Service Call outs are blocking activities. And that you should use workmanagers to solve performance problems resulting from the use of those blocking activities.

If you do nothing on dispatch policies in OSB proxy or business services, all is done in the Default Workmanager. But since some constructions, not only service call-outs, need other threads to finish the job, you can get stuck threads because the workmanager's threadpool gets empty having all or near to all threads waiting, leaving no threads to pickup work to free the others.

More on this in the terrific blog of Anthony Reynolds on the subject: Following the thread.

By the way,  I've seen that some people by default use service call-outs for almost everything. But the default use should be the routing node with a route activity. Even in some services you need to gather information from several sources, while you can only have one route node, pick or choose a 'driving-service' to use in the Routing node. Just like creating a query on several tables where you have to choose a 'driving-table'. Then  use service call outs only to do the extra enrichment.

From that earlier project I got the following recommendations, based on the blog of Anthony Reynolds. Since I refer back to it regularly, I think it would be good to share it.

For OSB to work optimally and prevent floading WebLogic’s threadpool with hogged/stuck threads you should create 3 FairShareRequest classes in ratio of 33/33/33, to distinguish different “kinds of threadpools”.

Then create 4 workmanagers:

  • FTPPollingWorkManager: file based inbound OSB proxy services. Polling a filesystem (or FTP). Uses FairShareReqClass-1, and ignores stuck threads.
  • InboudWorkManager: inbound OSB proxy services, not polling file based. Also uses FairShareReqClass-1, not ignoring stuck threads.
  • CallOutWorkManager: Service Call Out operations in a OSB proxy. Uses FairShareReqClass-2.
  • DeliveryWorkManager: outbound business services in OSB. Uses FairShareReqClass-3.
Use these as a dispatch policy in the particular Proxy/Business Services. In OSB 11g this is:
I don't have screendumps of 12c at hand. But the idea would be the same there. I haven't learned that the thread model in 12c is architecturally different.

Get the hostname of the executing server in BPEL

Wed, 2016-10-19 04:48
This week I got involved in a question on the Oracle Forums on getting the hostname of the server executing the bpel process. In itself this is not possible in BPEL. Also if you have a long running async process, the process gets dehydrated at several points (at a receive, wait, etc.). After an incoming signal, another server could process it further. You can't be sure that one server will process it to the end.

However, using Java, you can get the hostname of an executing server, quite easily. @AnatoliAtanasov suggested this question on stackOverflow. I thought that it would be fun to try this out.

Although you can opt for creating an embedded java activity, I used my earlier article on SOA and Spring Contexts to have it in a separate bean. By the way, in contrast to my suggestions in the article, you don't have to create a separate spring context for every bean you use.

My java bean looks like:
package nl.darwinit.soasuite;
import java.net.InetAddress;
import java.net.UnknownHostException;


public class ServerHostBeanImpl implements IServerHostBean {
public ServerHostBeanImpl() {
super();
}

public String getHostName(String hostNameDefault){
String hostName;
try
{
InetAddress addr;
addr = InetAddress.getLocalHost();
hostName = addr.getHostName();
}
catch (UnknownHostException ex)
{
System.out.println("Hostname can not be resolved");
hostName = hostNameDefault;
}
return hostName;
}

}

The interface class I generated is:
package nl.darwinit.soasuite;

public interface IServerHostBean {
String getHostName(String hostNameDefault);
}

Then I defined a Spring Context, getHostNameContext, with the following content
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:util="http://www.springframework.org/schema/util"
xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:sca="http://xmlns.oracle.com/weblogic/weblogic-sca" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://xmlns.oracle.com/weblogic/weblogic-sca META-INF/weblogic-sca.xsd">
<!--Spring Bean definitions go here-->
<sca:service name="GetHostService" target="ServerHostBeanImpl" type="nl.darwinit.soasuite.IServerHostBean"/>
<bean id="ServerHostBeanImpl" class="nl.darwinit.soasuite.ServerHostBeanImpl"/>
</beans>

After wiring the context to my BPEL the composite looks like:


Then, deploying and running it, gives the following output:


Nice, isn't it?

Weblogic 11g to 12c: strictness in listen address

Tue, 2016-10-18 07:50
Let's say you have a virtual machine with two network adapters, both set on 'HostOnly'.
I used to do that and set the first one of those to a fixed IP address, say 10.0.0.1. To this one I coupled the hostname, for instance darlin-vce-db, using the /etc/hosts file. That way I had a fixed, always existing network address for the database.

Together with the database, you install WebLogic, for instance to serve SOASuite, or OSB, or whatever custom application you want to serve. Now, wouldn't it be nice to be able to use WebLogic from a browser out of the virtual machine? Of course, because this is what you do nowadays: almost everywhere I come, servers are hosted on virtualized computing environments, like VMWare VSE or Oracle VM. So that's where the second adapter comes in, dynamically coupled to an address in the form of 192.168.56.101, for instance. Externally, using the etc/host file on your host OS (in my case Windows), you couple that address also to darlin-vce-db.

So you have two /etc/hosts settings for the hostname, darlin-vce-db:
In internally in the VM:
10.0.0.1        darlin-vce-db     darlin-vce-db.darwin-it.local
And externally on your host OS:
192.168.56.101  darlin-vce-db     darlin-vce-db.darwin-it.local

Nothing special, right? Well, WebLogic 11g, apparently just listens to the hostname 'darlin-vce-db', if that is entered as a listen-address. It seems not to care if the request for 'darlin-vce-db' comes from 192.168.56.101 in stead of the 10.0.0.1 to where the hostname actually is bound.

However, in this particular case WebLogic 12c seems to behave differently. If you provice 'darlin-vce-db' as listen address, that is bound to a network adapter that has 10.0.0.1 it expects that requests also come in via that network adapter. It seems to ignore requests that come in via other adapters (in my case 192.168.56.101).

You can solve this partially using Channels: in the Weblogic Console, navigate to the particular managed server, click Protocols, Channels.
Create a new channel:

Give it a name like 'Extern-Intern' or something else properly denoting the purpose of it and choose 'http' as a protocol:

Then Provide the internal address, for instance 'darlin-vce-db', and the external listen address:

Leave the ports to the default listen-port, in this case. Then finish the wizard.
Although this helps in connecting to the WebLogic console, EM, or with the same method on the SOA Server, to the SOA Composer (soaserver:port/soa/composer), BPM Workspace (soaserver:port/bpm/composer) etc., this will not work for JDeveloper.

When trying to deploy a soa composite from JDeveloper, you define/choose a ApplicationServer with connection to the AdminServer. But in case of deploying a composite, the AdminServer figures out which running SOA Servers there are, and let JDeveloper provide the composite to those servers. But then the soaserver(s) refuse(s) the connections from JDeveloper. Testing the ApplicationServer connection will show success for the Http connection to the AdminServer, but fails for all the other components.

The solution is then to denote a particular Network Adapter/ip address and make sure that internally and externally the particular hostname is coupled to that same particular ip-address.

OTN Appreciation Day: - the day after - BPEL, SOASuite and SCA (in that order...)

Wed, 2016-10-12 07:21
Unfortunately I noticed this nice initiative only yesterday: OTN Appreciation Day. I did not had a change to cook something up, but I do like to add some mustard after the meal, as we say in Dutch.

In the titles of the 'OTN Appreciation Day'-blogs I miss BPEL. In 2004,when Oracle acquired Collaxa, I worked at Oracle Consulting in the Netherlands. I worked with Oracle Workflow and Interconnect. Oracle wasn't yet into SOA really. But with BPEL PM they acquired the tool that stood at the base of SOA Suite, together with Webservices Manager and what we now know as the Mediator. And it changed my professional life, really. Its extremely powerful, especially with the added  JCA Adapters, xslt-mapper, and since 11g the SCA architecture wich enables you to assemble composite applications with Adapters BusinessRules, Human Workflow, Mediator, Spring Components and of course ... BPEL 2.0.

Sorry, Tim, for being late.

SQL Developer: Live and Let Live my db-connection

Wed, 2016-10-12 03:59
At my current customer I have SQLDeveloper open the whole day, and regularly I come back to it to query my throttle-table to see if my requests have been picked up. But regularly my database connection have been broken because of being idle. Probably because of a nasty firewall between my remote development desktop and the database.

Googling on it I found an article of That Jeff Smith on busy connections. That blog is really one to follow. Feed it to your Feedly if your a recent SQL Developer user.

But in my search I found the 'keepAlive-4' extension for SQL Developer 4. Download the KeepAlive zip, go to Help->Check for Updates in SQLDeveloper and install it via the 'Install From Local File' option. Then look for the Keep Alive icon in the toolbar:
Click on it and enter a check frequency, of at least 60 seconds. I try 180 seconds.

You can disable it by clicking it again. Another click and it asks for a new interval again.

Keep your Service Directory valid

Wed, 2016-10-05 07:49
To day I ran into a trap that trapped me before...

I tried to edit a file adapter service in SOA/BPM QuickStart 12.2.1. And got the error 'Service Directory is not valid' in a pop-up dialog, that prevents me from editing.

The problem is described in this forum thread.

The problem is a space in the path to the JDeveloper project. Now spaces are a drag in filenames and paths (I hate it that Microsoft Windows introducced "Program Files" as the default folder for installing applications).

The solution is in Windows quite simple actually: create a substitute drive like:
echo define drive S: referring to current folder
subst s: /d
subst s: "d:\Data\svn\Applicatie Integration"

Put this in a .bat file and run it before starting JDeveloper and load the application workspaces from the S: drive.

I had this already in place because of my first run into this trap. Why I tripped again? It turned out I accidentally had opened the application from the d: drive again...

Use WLST to test all your datasources

Tue, 2016-10-04 07:10
To day I had some problems with deploying my composite to the server of my current customer. Apparently the Server had some problems with datasources. But since there are many I did not feel much for checking them one by one with the console. Using Google I got the following examples

Thus I had to combine those two, sauce it with my own way of wlst-scripting (see my other blog entries). Also I want a tabular form, that got me into troubles with printing the result of the testPool() method. But I came up with the following script, testDS.py:
#############################################################################
# Test Datasources on a domain
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-10-04
#
#############################################################################
# Modify these values as necessary
import sys, traceback
scriptName = sys.argv[0]
#
#
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=hhs-sbm3015:7001"
print "adminUser=weblogic"
print "adminPwd=welcome1"
#
#
def connectToadminServer(adminUrl, adminServerName):
print(lineSeperator)
print('Try to connect to the AdminServer')
try:
connect(userConfigFile=usrCfgFile, userKeyFile=usrKeyFile, url=adminUrl)
except NameError, e:
print('Apparently user config properties usrCfgFile and usrKeyFile not set.')
print('Try to connect to the AdminServer adminUser and adminPwd properties')
connect(adminUser, adminPwd, adminUrl)
#
#
def main():
try:
pad=' '
print(lineSeperator)
print('Check datasources for domain')
print(lineSeperator)
print ('Connect to the AdminServer: '+adminServerName)
connectToadminServer(adminUrl, adminServerName)
print(lineSeperator)
allServers=domainRuntimeService.getServerRuntimes();
if (len(allServers) > 0):
for tempServer in allServers:
jdbcServiceRT = tempServer.getJDBCServiceRuntime();
dataSources = jdbcServiceRT.getJDBCDataSourceRuntimeMBeans();
print('\nServer '+tempServer.getName())
if (len(dataSources) > 0):
print('Datasource '[:30]+'\tState\tTest')
for dataSource in dataSources:
testPool = dataSource.testPool()
dataSourceName = dataSource.getName()+pad
dataSourceNamePad=dataSourceName[:30]
if (testPool == None):
print dataSourceNamePad+'\t'+dataSource.getState()+'\tOK'
else:
print dataSourceNamePad+'\t'+dataSource.getState()+'\tFailure: '
print testPool
print(lineSeperator)
print('Done...')
print(lineSeperator)
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())
exit(exitcode=1)
#
main();

Of course it's easy to extent the table with properties from the monitor script in WebLogic DataSource Monitoring Using WLST.

Which runs pretty neat. Run it with a shell script like the following testDS.sh script:
#!/bin/bash
#############################################################################
# Test DataSources using wlst.
#
# @author Martien van den Akker, Darwin-IT Professionals
# @version 2.1, 2016-06-27
#
#############################################################################
#
. fmw12c_env.sh
echo
echo Test Datasources
wlst.sh ./testDS.py -loadProperties fmw.properties

For the fmw12c_env.sh and fmw.properties files look here.

Pages