Configuring Mariadb datasources in wildfly

While i had been using glassfish/payara for most of my projects, i decided to switch to Wildfly for a project in which i preferred to have ActiveMQ als a JMS provider.

Using the JBOSS_CLI to create the JMS configurations was quite easy, but i did have a small challenge in figuring out how to create the mariadb driver/(xa)datasource.

This is what i ended up using:

1. Configure-buildTime.sh – a script that i run during docker build

# Download the maria-db driver
curl https://downloads.mariadb.com/Connectors/java/connector-java-2.7.2/mariadb-java-client-2.7.2.jar > /opt/jboss/mariadb.driver.jar
# Execute the client script that will register the driver & datasources
$JBOSS_CLI --file=/opt/jboss/wildfly/jdbc.command.cli

2. jdbc.command.cli – the JBOSS_CLI script that registers the driver and datasources.

connect
batch

module add \
 --name=org.mariadb \
 --dependencies=javax.api,javax.transaction.api \
 --resources=/opt/jboss/mariadb.driver.jar \

/subsystem=datasources/jdbc-driver=mariadb:add(driver-name="mariadb", driver-module-name="org.mariadb", driver-class-name="org.mariadb.jdbc.Driver", driver-xa-datasource-class-name="org.mariadb.jdbc.MariaDbDataSource")

data-source add \
 --name=MyDatasource \
 --jndi-name=java:/jdbc/MyDatasource \
 --driver-name=mariadb \
 --connection-url=jdbc:mysql://${env.RDS_HOSTNAME:${env.RDS_HOSTNAME}}:${env.RDS_PORT:${env.RDS_PORT}}/${env.RDS_DB_NAME:${env.RDS_DB_NAME}} \
 --user-name=${env.RDS_USERNAME:${env.RDS_USERNAME}} \
 --password=${env.RDS_PASSWORD:${env.RDS_PASSWORD}} \
 --check-valid-connection-sql="/* ping */ SELECT 1"

xa-data-source add --name=MyDatasourceXA \
 --driver-name=mariadb \
 --jndi-name=java:/jdbc/MyDatasourceXA \
 --user-name=${env.RDS_USERNAME:${env.RDS_USERNAME}} \
 --password=${env.RDS_PASSWORD:${env.RDS_PASSWORD}} \
 --recovery-username=${env.RDS_USERNAME:${env.RDS_USERNAME}} \
 --recovery-password=${env.RDS_PASSWORD:${env.RDS_PASSWORD}} \
 --xa-datasource-properties=Url=jdbc:mysql://${env.RDS_HOSTNAME:${env.RDS_HOSTNAME}}:${env.RDS_PORT:${env.RDS_PORT}}/${env.RDS_DB_NAME:${env.RDS_DB_NAME}} \ 
 --xa-datasource-class=org.mariadb.jdbc.MariaDbDataSource\
 --check-valid-connection-sql="/* ping */ SELECT 1"

run-batch

exit

Notice how i give my parameters a default value recursing to the parameter itself. This is done because the JBOSS_CLI apparantly tries to expand the values (although default configured not to do so version 21.0.1), and i could not find another way to prevent this – it feels like a bug. My goal was to have the parameters to be resolved at image-runtime – and that worked!

3. My war/META-INF/persistence.xml

..
<jta-data-source>jdbc/MyDatasourceXA</jta-data-source>
..

Configure Selenium EdgeDriver to prevent uri/protocol_handler popups.

I just spend a few hours on this, so here’s a quick public not for anyone trying to do selenium testing on Microsoft Edge Chromium that runs into a popup for custom uri-handlers:

You can disable them by passing the following code-block as experimental options in microsoft edge.

{	"protocol_handler": {
		"allowed_origin_protocol_pairs": {
			"http://h2916922.stratoserver.net:8084.nl": {
				"myUriHandler": true
			}
		}
	}
}

Here’s my proof of concept / quick and dirty implementation in java:

		EdgeDriver driver = null;
		EdgeOptions opt=new EdgeOptions();

		String protocolHandlerSetting="	{\"protocol_handler\": {\r\n"
			+ "		\"allowed_origin_protocol_pairs\": {\r\n"
			+ "			\"http://h2916922.stratoserver.net:8084\": {\r\n"
			+ "				\"myUriHandler\": true\r\n"
			+ "			}\r\n"
			+ "		}\r\n"
			+ "	}}";
		
		opt.setExperimentalOption("prefs", new Gson().fromJson(protocolHandlerSetting, HashMap.class));
		
		driver = new EdgeDriver(opt);
		driver.get("http://h2916922.stratoserver.net:8084");

Enjoy!

Automatically accept certificates using the wsadmin.bat/sh

Today i’ve been trying to execute jython to manage my websphere from java. By utilizing the “com.ibm.ws.scripting.WasxShell” class i was hoping to be able to execute java using only the thick-client and jython libraries on my classpath.

Did not quite get there, but did catch something else – a simple way to automatically accept self-signed certificates, by leveraging websphere’s signer auto-exchange prompt . When set to stdin, you can just echo y to answer adding the certificate.

echo y | "${wsadmin.dir}\wsadmin.bat" -javaoption="-Dcom.ibm.ssl.enableSignerExchangePrompt=stdin" -conntype SOAP -host ${host} -port ${port} -user ${user} -password ${password} -lang jython -f "${scriptfile}"

Alternatively you might also go for a more explicit/controlled approach mentioned on notonlyanecmplace.com

Phasing out values from Content Navigator Choicelists

With Corona on the verge of closing schools and daycare in the coming week, i figured it was a good time to do some client-work, so i logged in. Immediately i found a colleague online as well (on a Sunday?!) . Anyway, he was working on a little script that needed some finetuning.

The script was to allow content-navigator render values that were no-longer valid according to EDS / Filenet (think of migrated content). The OOTB implementation would just “hide” them.

Eventually we tinkered the following:

require([
        "dojo/_base/declare",
        "dojo/_base/lang",
        "dojo/aspect",
        "ecm/widget/LayoutPropertiesPane"
    ],
    function(declare,
        lang,
        aspect,
        LayoutPropertiesPane) {

        aspect.around(LayoutPropertiesPane.prototype, "renderAttributes", function(originalrenderAttributes) {
            return function(attributeDefinitions, item, reason, isReadOnly, params) {

                attributeDefinitions.forEach(function(def) {

                    function addChoiceIfNotExists(value) {
                        var choiceExists = def.choiceList.choices.some(function(choice) {
                            return choice.value === value
                        });
                        if (!choiceExists) {
                            def.choiceList.choices.push({
                                valid: true,
                                displayName: value + " - deprecated",
                                value: value
                            });
                        }
                    }

                    if (def.choiceList) {
                        if (def.cardinality === "LIST") {
                            item.getValues(def.id).forEach(addChoiceIfNotExists);
                        } else if (def.cardinality === "SINGLE") {
                            addChoiceIfNotExists(item.getValue(def.id));
                        } else {
                            throw "Unexpected choicelist cardinality";
                        }
                    }
                });

                originalrenderAttributes.apply(this, arguments);
            }
        });
    });

Credits of course to my colleague with the long name 😉 Bruno Raphael Marques de Santana.

Glassfish no longer logging? It’s probably due to expired certificates!

A few days ago i noticed my webapp running on glassfish wasn’t producing any log anymore  within eclipse. After mingling a bit with the log configuration, i finally decided to go for a fresh glassfish 5 setup, and again i had logging.

However, after a while i again lost my logging. And, although i’m not sure why, it seems that the expiration of SSL certificates turned out to be the cause.

2018-11-22T16:16:51.803+0100|Severe: The SSL certificate has expired: [
[
  Version: V3
  Subject: OU=Equifax Secure Certificate Authority, O=Equifax, C=US
  Signature Algorithm: SHA1withRSA, OID = 1.2.840.113549.1.1.5
  Key:  Sun RSA public key, 1024 bits
  modulus: 135786214035069526348186531221551781468391756233528066061569654028671100866720352830303278016129003918213826297308054231261658522889438712013757624116391437358730449661353175673177742307421061340003741057138887918110217006515773038453829253517076741780039735595086881329494037450587568122088113584549069375417
  public exponent: 65537
  Validity: [From: Sat Aug 22 18:41:51 CEST 1998,
               To: Wed Aug 22 18:41:51 CEST 2018]
  Issuer: OU=Equifax Secure Certificate Authority, O=Equifax, C=US
  SerialNumber: [    35def4cf]
Certificate Extensions: 7
[1]: ObjectId: 1.2.840.113533.7.65.0 Criticality=false
Extension unknown: DER encoded OCTET string =
0000: 04 0D 30 0B 1B 05 56 33   2E 30 63 03 02 06 C0     ..0...V3.0c....
[2]: ObjectId: 2.5.29.35 Criticality=false
AuthorityKeyIdentifier [
KeyIdentifier [
0000: 48 E6 68 F9 2B D2 B2 95   D7 47 D8 23 20 10 4F 33  H.h.+....G.# .O3
0010: 98 90 9F D4                                        ....
]
]
[3]: ObjectId: 2.5.29.19 Criticality=false
BasicConstraints:[
  CA:true
  PathLen:2147483647
]
[4]: ObjectId: 2.5.29.31 Criticality=false
CRLDistributionPoints [
  [DistributionPoint:
     [CN=CRL1, OU=Equifax Secure Certificate Authority, O=Equifax, C=US]

Now, in order to get restore your logging, all you need to do is to remove the expired certificates from your glassfish configuration.

Follow these two steps:

  1. Navigate to your glassfish / domain / config directory.
    cd glassfish5\glassfish\domains\domain1\config
  2. Find out the ‘alias’ for the expired certificates mentioned in the log.
    keytool -v -list -keystore cacerts.jks
    * the above sample will resolve to ‘equifaxsecureca’
  3. Remove the certificate from glassfish
    keytool -delete -keystore cacerts.jks -alias equifaxsecureca -storePass changeit
  4. Restart glassfish, and observe you’re logging is back 🙂

Update 28 july 2019: I currently use the below scripot to remove outdated certificates from glassfish & payara in my docker scripts:

RUN			cd ${GLASSFISH_HOME}/glassfish/domains/domain1/config/ && \
			for cert in "equifaxsecureca" "gtecybertrustglobalca" "utnuserfirstclientauthemailca" "deutschetelekomrootca2" "secomvalicertclass1ca" "valicertclass2ca" "entrustsslca" "certplusclass2primaryca" "certplusclass3pprimaryca" "utndatacorpsgcca" "utnuserfirstobjectca" "utnuserfirstobjectca [jdk]" "utnuserfirsthardwareca" "cert_45_deutsche_telekom_root_ca_245" "cert_29_certplus_class_2_primary_ca29" "cert_38_deutsche_telekom_root_ca_238" "utnuserfirsthardwareca [jdk]" "certplusclass3pprimaryca [jdk]" "certplusclass2primaryca [jdk]" "utnuserfirstclientauthemailca [jdk]"; \
			do \
			keytool -delete -keystore cacerts.jks -alias "$cert" -storePass changeit || echo "nothing to remove";\
			done

A little writing pause

I’ve been receiving a lot of pm’s as of late asking why i’m no longer writing on my blog. The reason is quite easy, i’ve recently become father of my second and am simply too busy.

While i am still coding a lot and doing cool stuff, i simply just currently don’t have the time to write about it. I am however creating drafts, but hardly have the time to finish those posts 🙂

Will definitively catch up later!

Adjusting/Overriding IBM Content Navigator front-end labels and captions.

Although all my clients have requirements to update or change OOTB labels used in Case Manager, i wasn’t able to find a best practice to do so. So i decided to look for it on my own.

As it turns out all labels are stored in localized files located at “navigator.ear\navigator.war\ecm\nls\”. Obviously one way would be to directly change these files, but that would be just a bad idea.

The localized messages will eventually be loaded in the ecm/Messages namespace when loading the ICN libraries (.navigator/ecm/nls/ecm_en.js). Knowing this, i believe it to be a good suggestion to use the following code to override OOTB messages in a non-invasive fashion.

require(["ecm/Messages"],function(Messages){

	Messages.launchbar_browse="Open the browser!:)";

});

The code would be best loaded via the bootstrap of a plugin that is the first plugin te be loaded. (See the “move up” button in your ?desktop=admin/plugins)

Additional info: A list of all Messages you might want to override.

Asynchronously emitting from a scriptadapter

The regular use of a IBM CaseManager ScriptAdapter allows you to specify a payload that is (synchronously) emitted after it is triggered by an incoming event. But, did you know it is also an option to asynchronously emit the payload?

Its quite easy, and it’s done by:

  1. Disabling the default outgoing payload
  2. Manually call for an emit by calling:
this.onPublishEvent("icm.SendEventPayload",payload);

 

While this may seem like a trivial functionality, it can actually be used to fix challenges such as:

  1. Emitting a document/folder/task/case(editable) that not yet has its full attributes retrieved. Simply call the retrieveAttributes before emitting.
  2. Split up payloads by wiring, e.g. handle each result of an ecm.model.SearchQuery.
    (for each result -> emit wire -> show document in viewer)
  3. Waits & polling. E.g. Wait for a certain event to happen, then finally emit.

 

Useful, right?

Using CSS in the pagebuilder – CSS-adapter

Allright, for everyone who has end-users requesting minimal changes to your page, check this out:

Below is a simple widget you can place on your page to add scoped CSS to your page, or layout elements in a fashion that is 100% in line with the page-builder philosophy and is very maintainable.

Dummy example implementation:

Works out:

The widget package can be downloaded here, the source can be found here.

Enjoy!

Wiring tab-layout open/close/.. events (freeform design ICM 5.3)

Case Manager 5.3. introduced the free-form page-layout, a feature two of my clients have been longing to for a long time. In fact, one of my clients had their own tab-container implementation written almost two years ago.

Anyway, while the free-form page-layout and newly introduced tab-container are one of the most cheered-at new features, it turned out both clients had a set of custom widgets that needed manual refreshing, preferably when the corresponding tab was clicked (the tab was re-opened if you will).

In order to achieve this, i created a ‘adapter widget’ that can be placed within a tab to detect the following events:

  • The tab was opened,
  • The tab was closed,
  • The tab same tab was opened again (refreshed)
  • The tab was created.

The events then can be wired to other widgets / script adapters.

This adapter both works for the new freeform layout tab’s, as well as the page-tabs.

 

You can download the pre-compiled widget-package here. The source can be downloaded here. All under MIT license.

Widget package tested under 5.2 (for use in page-tabs), 5.3 and 5.3.1.

 

Related post: Adding new functionality to the CaseBuilder Advanced lay-outing with the page designer