Monday, 11 March 2019

Upgrade SOASuite process to 12c - Sensor Actions JMS to AQ

At my current customer we're busy with upgrading our projects from 11g to 12c.

One of the solution my predecessors implemented, is to kick of archive processes using sensor actions.The archive processes listen to JMS Queues, that are implemented as AQ Queues. For that a Foreign Server is configured:

The Foreign Server has a reference to the datasource that points to the schema owning the queues. It has also one or more Connnection Factories:

And the queues have a mapping from a local JNDI to a remote JNDI. The remote JNDI is the name of the particular queue prefixed with Queue:

In the sensor actions we used to have a JMS Adapter configured with as a connection factory the JNDI name of the outbound connection pool, for instance eis/aqjms/DwnQueueDB. The connection factory in that outbound connection factory refers to the JNDI of the connection factory in the Foreign Server.

Now, it turned out that our archiving processes weren't kicked off. I found a few things.

Sensor property files

The sensors can be configured using in the Monitor view of the BPEL Designer. It can be accessed using the Monitor Icon top left. When an Sensor is defined you can click the attena icon. You can of course create new ones by right clicking on the activity.
Sensor actions can be edited by selecting them and click the pencil-edit-icon.


In 11g, all the artefacts land in the root folder of the composite by default. We refactored the composites by moving artefacts to respective folders, like SOA Suite 12c would do in a new project.
But we skipped the files ${bpel-process-name}_sensor.xml and ${bpel-process-name}_sensorAction.xml.  I moved those to the same folder as the BPEL process. With a refresh, the attena-icons re-appeared.

But, also the files are referenced in the composite.xml:
…
</componentType>
    <property name="configuration.sensorLocation" type="xs:string" many="false">BPEL/${bpel-process-name}_sensor.xml</property>
    <property name="configuration.sensorActionLocation" type="xs:string" many="false">BPEL/${bpel-process-name}_sensorAction.xml</property>
  </component>

These references aren't updated automatically when moving them. But it turns out that the properties are renamed as well (probably from 10g to 11g already):
  • pre-11g:  bpel.config.sensorLocation => 11g/12c onwards: configuration.sensorLocation
  • pre-11g:  bpel.config.sensorActionLocation=> 11g/12c onwards: configuration.sensorActionLocation

JMS Adapter doesn't register the properties

As said, we used to use the JMS Adapter. I found that after the modifications to properly reference the sensor/sensorAction files, the message was published, but not picked up. The Listening archive process had a Message Selector like: BPEL_SENSOR_NAME like 'MySensorName%'.

I have a query that allows me to select from the queue tables and introspect the queues as JMS Queues:
select  qtb.queue_table 
, qtb.queue 
, qtb.msg_id
, qtb.msg_state
, qtb.enq_timestamp
, qtb.user_data.header.replyto
, qtb.user_data.header.type type
, qtb.user_data.header.userid userid
, qtb.user_data.header.appid appid
, qtb.user_data.header.groupid groupid
, qtb.user_data.header.groupseq groupseq
, qtb.user_data.header.properties properties
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'tracking_compositeInstanceId') tracking_compositeInstanceId
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'JMS_OracleDeliveryMode') JMS_OracleDeliveryMode
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'tracking_ecid') tracking_ecid
, (select num_value from table (qtb.user_data.header.properties) prp where prp.name = 'JMS_OracleTimestamp') JMS_OracleTimestamp
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'tracking_parentComponentInstanceId') tracking_prtCptInstanceId
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'tracking_conversationId') tracking_conversationId
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'BPEL_SENSOR_NAME') bpel_sensor_name
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'BPEL_PROCESS_NAME') bpel_process_name
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'BPEL_PROCESS_REVISION') bpel_process_rev
, (select str_value from table (qtb.user_data.header.properties) prp where prp.name = 'BPEL_DOMAIN') bpel_domain
, qtb.user_data.header
, qtb.user_data.text_lob text
, qtb.expiration_reason
--, qtb.*
from ( select 'DWN_OUTBOUND_TABLE' queue_table
       , qtb.* 
       from aq$dwn_outbound_table qtb
       union all
       ...
       union all
       select 'DWN_INBOUND_TABLE' queue_table
       , qtb.*
       from AQ$DWN_INBOUND_TABLE qtb) qtb
order by enq_timestamp desc;

This query lists the contents of several queue tables (always query queue tables via their AQ$Queue_table_name view) unioned together. From that you can introspect the user data and their properties witht he dot notation. The UserData has a header object, that contains a properties collection, that holds the JMS properties. You can select those as seen above.  It turns out that Sensor Actions should set the followign properties:
  • BPEL_SENSOR_NAME
  • BPEL_PROCESS_NAME
  • BPEL_PROCESS_REVISION
  • BPEL_DOMAIN
I found that using the JMS Adapter as a publish type in the SensorAction, these properties aren't set in 12c. While they apparently were in 11g.

After some researching, with no luck, I figured that I could try using a JMS Queue configuration. I wondered what the difference would be. Well, it turned out that using a JMS Queue did work.
Reconfiguring the Sensor Action to use a JMS Queue  means:
  • Set Publish Type to JMS Queue (obviously)
  • The JMS Connection Factory need to hold the JNDI name of the connection factory to use. In our case the one registered at the Foreign Server. (With JMSAdapter as Publish Type, this property is called JMSConnectionName.)
  • The Publish Target is now the JNDI Name of the destination. In our example (see the screen shot above) it is the local jndi of the queue to publish to. With the JMS Adapter it was the queue name.

So, in our case this worked.



No comments:

Post a Comment