From 4d7453eb57b226d0a978a8c2fc10cb077f5bec3c Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Fri, 13 Sep 2024 08:00:25 +0530 Subject: [PATCH 01/26] JDBC - Advanced Queueing fixes First round of edits --- .../42.7.3.1/05a_using_advanced_queueing.mdx | 150 +++++++++++------- .../docs/jdbc_connector/42.7.3.1/index.mdx | 2 +- 2 files changed, 92 insertions(+), 60 deletions(-) diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx index a151fbf5467..c463afbf09e 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx @@ -9,7 +9,7 @@ indexdepth: 3 EDB Postgres Advanced Server advanced queueing provides message queueing and message processing for the EDB Postgres Advanced Server database. User-defined messages are stored in a queue, and a collection of queues is stored in a queue table. You must first create a queue table before creating a queue that depends on it. -On the server side, procedures in the `DBMS_AQADM` package create and manage message queues and queue tables. Use the `DBMS_AQ` package to add or remove messages from a queue or register or unregister a PL/SQL callback procedure. For more information about `DBMS_AQ` and `DBMS_AQADM`, see the [DBMS_AQ](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/02_dbms_aq/). +On the server side, procedures in the `DBMS_AQADM` package create and manage message queues and queue tables. Use the `DBMS_AQ` package to add or remove messages from a queue or register or unregister a SPL callback procedure. For more information about `DBMS_AQ` and `DBMS_AQADM`, see the [DBMS_AQ](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/02_dbms_aq/). On the client side, the application uses EDB-JDBC driver's JMS API to enqueue and dequeue message. @@ -21,27 +21,36 @@ For more information about using EDB Postgres Advanced Server's advanced queuein To use advanced queueing functionality on your JMS-based Java application perform following steps in EDB-PSQL or EDB-JDBC: -1. Create a user-defined message type, which may be one of the standard JMS message types. However, EDB JDBC also supports any user-defined types. These types will be covered in detail in the upcoming sections. -2. Create a queue table specifying the payload type. This type will typically be the one created in step 1. -3. Create a queue using the queue table created in the previous step. -4. Start the queue on the database server. -5. You have the option to use either EDB-PSQL or EDB-JDBC JMS API in your Java application. +1. Create a user-defined message type, which may be one of the standard JMS message types. However, EDB-JDBC also supports any user-defined message types. These [message types](#message-types) will be covered in detail in the upcoming sections. +1. Create a queue table specifying the payload type. This type will typically be the one created in step 1. +1. Create a queue using the queue table created in the previous step. +1. Start the queue on the database server. +1. You have the option to use either [EDB-PSQL](#using-edb-psql) or [EDB-JDBC JMS API](#using-edb-jdbc-jms-api) in your Java application. ### Using EDB-PSQL -Invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Use the following SPL commands at the command line. +Invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Use the SPL commands in EDB-PSQL to: -**Creating a user-defined type** +- [Create a user-defined type](#create-a-user-defined-type) +- [Create the queue table](#create-a-user-defined-type) +- [Create the queue](#create-the-queue) +- [Start the queue](#start-the-queue) -To specify a RAW data type, create a user-defined type. This example creates a user-defined type named as `mytype`. +#### Create a user-defined type** + +To specify a RAW data type, create a user-defined type. + +This example shows how to create a user-defined type named as `mytype`: ```sql CREATE OR REPLACE TYPE mytype AS (code INT, project TEXT, manager VARCHAR(10)); ``` -**Create the queue table** +#### Create the queue table + +A queue table can hold multiple queues with the same payload type. -A queue table can hold multiple queues with the same payload type. This example creates a table named `MSG_QUEUE_TABLE`. +This example shows how to create a queue table named `MSG_QUEUE_TABLE`: ```sql EXEC DBMS_AQADM.CREATE_QUEUE_TABLE @@ -51,9 +60,9 @@ EXEC DBMS_AQADM.CREATE_QUEUE_TABLE END; ``` -**Create the queue** +#### Create the queue -This example creates a queue named `MSG_QUEUE` in the table `MSG_QUEUE_TABLE`. +This example shows how to create a queue named `MSG_QUEUE` in the table `MSG_QUEUE_TABLE`: ```sql EXEC DBMS_AQADM.CREATE_QUEUE @@ -62,9 +71,11 @@ EXEC DBMS_AQADM.CREATE_QUEUE comment => 'This queue contains pending messages.'); ``` -**Start the queue** +#### Start the queue -Once the queue is created, invoke the following SPL code at the command line to start a queue in the EDB database. +Once the queue is created, start the queue. + +This example shows how to start a queue in the database: ```sql EXEC DBMS_AQADM.START_QUEUE(queue_name => 'MSG_QUEUE'); @@ -78,6 +89,7 @@ The following sequence of steps is required only if you want to create message t !!! The following JMS API calls perform the same steps performed using EDB-PSQL to: + - Connect to the EDB Postgres Advanced Server database - Create the user-defined type - Create the queue table and queue @@ -111,7 +123,7 @@ queue.start(); After creating the queue table and queue for the message types and starting the queue, you can follow these steps to set up your JMS Application: -1. Create a [Connection Factory](#connection-factory). +1. Create a [Connection factory](#connection-factory). 1. Create a [Connection](#connection) using the connection factory. 1. Create a [Session](#session) using the connection. 1. Get the Queue from the session. @@ -123,7 +135,7 @@ After creating the queue table and queue for the message types and starting the ### Connection factory -The Connection Factory is used to create connections. EDBJmsConnectionFactory is an implementation of ConnectionFactory and QueueConnectionFactory, used to create Connection and QueueConnection. A connection factory can be created using one of the constructors of the EDBJmsConnectionFactory class. All three constructors can be used to create either a ConnectionFactory or QueueConnectionFactory. +The `Connection factory` is used to create connections. `EDBJmsConnectionFactory` is an implementation of `ConnectionFactory` and `QueueConnectionFactory`, used to create `Connection` and `QueueConnection`. A `Connection factory` can be created using one of the constructors of the `EDBJmsConnectionFactory` class. All three constructors can be used to create either a `ConnectionFactory` or `QueueConnectionFactory`. ```java //Constructor with connection related properties. @@ -136,13 +148,13 @@ public EDBJmsConnectionFactory(String connectionString, public EDBJmsConnectionFactory(java.sql.Connection connection); ``` -This example shows how to create a ConnectionFactory using an existing `java.sql.Connection`: +This example shows how to create a `ConnectionFactory` using an existing `java.sql.Connection`: ```java javax.jms.ConnectionFactory connFactory = new EDBJmsConnectionFactory(connection); ``` -This example shows how to create a QueueConnectionFactory using a connection string, username, and password: +This example shows how to create a `QueueConnectionFactory` using a connection string, username, and password: ```java javax.jms.QueueConnectionFactory connFactory = new EDBJmsConnectionFactory @@ -151,9 +163,9 @@ javax.jms.QueueConnectionFactory connFactory = new EDBJmsConnectionFactory ### Connection -A Connection is a client's active connection that can be created from the ConnectionFactory and used to create sessions. EDBJmsConnection is an implementation of Connection, while EDBJmsQueueConnection is an implementation of QueueConnection and extends EDBJmsConnection. A Connection can be created using ConnectionFactory, while QueueConnection can be created from QueueConnectionFactory. +A `Connection` is a client's active connection that can be created from the `ConnectionFactory` and used to create sessions. `EDBJmsConnection` is an implementation of `Connection`, while `EDBJmsQueueConnection` is an implementation of `QueueConnection` and extends `EDBJmsConnection`. A `Connection` can be created using `ConnectionFactory`, while `QueueConnection` can be created from `QueueConnectionFactory`. -This example shows how to create a Connection and a QueueConnection: +This example shows how to create a `Connection` and a `QueueConnection`: ```java //Connection from ConnectionFactory. Assuming connFactory is ConnectionFactory. @@ -163,7 +175,9 @@ javax.jms.Connection connection = connFactory.createConnection(); javax.jms.QueueConnection queueConnection = connFactory.createQueueConnection(); ``` -A connection must be started in order for the consumer to receive messages. On the other hand, a producer can send messages without starting the connection. To start a connection, use the following code: +A connection must be started in order for the consumer to receive messages. On the other hand, a producer can send messages without starting the connection. + +This example shows how to start a connection: ```java queueConnection.start(); @@ -171,7 +185,7 @@ queueConnection.start(); A connection can be stopped at any time to cease receiving messages, and can be restarted when needed. However, a closed connection cannot be restarted. -To stop and close the connection, use the following code: +This example shows how to stop and close the connection: ```java queueConnection.stop(); @@ -180,9 +194,9 @@ queueConnection.close(); ### Session -The Session in EDBJms is used for creating producers and consumers, and for sending and receiving messages. EDBJmsSession implements the basic Session functionality, while EDBJmsQueueSession extends EDBJmsSession and implements QueueSession. A session can be created from a Connection. +The `Session` in EDBJms is used for creating producers and consumers, and for sending and receiving messages. `EDBJmsSession` implements the basic `Session` functionality, while `EDBJmsQueueSession` extends `EDBJmsSession` and implements `QueueSession`. A `Session` can be created from a `Connection`. -This example shows how to create a Session and a QueueSession: +This example shows how to create a `Session` and a `QueueSession`: ```java // Session @@ -191,7 +205,11 @@ javax.jms.Session session = connection.createSession(false, javax.jms.Session.AU javax.jms.QueueSession session = queueConnection.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); ``` -A Session or QueueSession is also used to create queues. It's important to note that in this context, "creating a queue" does not refer to physically creating the queue. As discussed earlier, the queue needs to be created and started as part of the server-side setup. In this context, creating a queue means getting the queue, related queue table, and payload type that have already been created. +A `Session` or `QueueSession` is also used to create queues. + +!!!note "Important" +In this context, "creating a queue" does not refer to physically creating the queue. As discussed earlier, the queue needs to be created and started as part of the server-side setup. In this context, creating a queue means getting the queue, related queue table, and payload type that have already been created. +!!! This example shows how to create a queue: @@ -201,7 +219,7 @@ javax.jms.Queue queue = session.createQueue("MSG_QUEUE"); ### Message producer -A message producer is responsible for creating and sending messages. It is created using a session and queue. EDBJmsMessageProducer is an implementation of MessageProducer, but in most cases, you will be using the standard MessageProducer. +A `Message producer` is responsible for creating and sending messages. It is created using a session and queue. `EDBJmsMessageProducer` is an implementation of `MessageProducer`, but in most cases, you will be using the standard `MessageProducer`. This example shows how to create a message producer, create a message, and send it. Creating messages of different types will be discussed in the following sections. @@ -216,7 +234,7 @@ messageProducer.send(msg); ### Message consumer -A Message consumer is used to receive messages. It is created using a session and a queue. EDBJmsMessageConsumer is an implementation of MessageConsumer, but you will most often use the standard MessageConsumer. +A `Message consumer` is used to receive messages. It is created using a session and a queue. `EDBJmsMessageConsumer` is an implementation of `MessageConsumer`, but you will most often use the standard `MessageConsumer`. This example shows how to create a message consumer and receive a message: @@ -228,7 +246,7 @@ javax.jms.Message message = messageConsumer.receive(); ### Message acknowledgement -Acknowledgement of messages is controlled by the two arguments to the createSession() and createQueueSession() methods: +Acknowledgement of messages is controlled by the two arguments to the `createSession()` and `createQueueSession()` methods: ```java EDBJmsConnection.createSession(boolean transacted, int acknowledgeMode) @@ -236,18 +254,19 @@ EDBJmsConnection.createSession(boolean transacted, int acknowledgeMode) EDBJmsQueueConnection.createQueueSession(boolean transacted, int acknowledgeMode) ``` -If the first argument is true, it indicates that the session mode is transacted, and the second argument is ignored. However, if the first argument is false, then the second argument comes into play, and the client can specify different acknowledgment modes. These acknowledgment modes include, +If the first argument is true, it indicates that the session mode is transacted, and the second argument is ignored. However, if the first argument is false, then the second argument comes into play, and the client can specify different acknowledgment modes. + +These acknowledgment modes include, + - Session.AUTO_ACKNOWLEDGE - Session.CLIENT_ACKNOWLEDGE - Session.DUPS_OK_ACKNOWLEDGE -The following sections describe different modes of acknowledgement: - ## Transacted session -In transacted sessions, messages are both sent and received during a transaction. These messages are acknowledged by making an explicit call to commit(). If rollback() is called, all received messages will be marked as not acknowledged. +In transacted sessions, messages are both sent and received during a transaction. These messages are acknowledged by making an explicit call to `commit()`. If `rollback()` is called, all received messages will be marked as not acknowledged. -A transacted session always has an active transaction. When a client calls the commit() or rollback() method, the current transaction is either committed or rolled back, and a new transaction is started. +A transacted session always has an active transaction. When a client calls the `commit()` or `rollback()` method, the current transaction is either committed or rolled back, and a new transaction is started. This example explains how the transacted session works: @@ -311,15 +330,15 @@ This example explains how the transacted session works: ### AUTO_ACKNOWLEDGE mode -If the first argument to createSession() or createQueueSession() is false and the second argument is Session.AUTO_ACKNOWLEDGE, the messages are automatically acknowledged. +If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.AUTO_ACKNOWLEDGE`, the messages are automatically acknowledged. ### DUPS_OK_ACKNOWLEDGE mode -This mode instructs the session to lazily acknowledge the message, and it is okay if some messages are redelivered. However, in EDB JMS, this option is implemented the same way as Session.AUTO_ACKNOWLEDGE, where messages will be acknowledged automatically. +This mode instructs the session to lazily acknowledge the message, and it is okay if some messages are redelivered. However, in EDB JMS, this option is implemented the same way as `Session.AUTO_ACKNOWLEDGE`, where messages will be acknowledged automatically. ### CLIENT_ACKNOWLEDGE mode -If the first argument to createSession() or createQueueSession() is false and the second argument is Session.CLIENT_ACKNOWLEDGE, the messages are acknowledged when the client acknowledges the message by calling the acknowledge() method on a message. Acknowledging happens at the session level, and acknowledging one message will cause all the received messages to be acknowledged. +If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.CLIENT_ACKNOWLEDGE`, the messages are acknowledged when the client acknowledges the message by calling the `acknowledge()` method on a message. Acknowledging happens at the session level, and acknowledging one message will cause all the received messages to be acknowledged. For example, if we send 5 messages and then receive the 5 messages, acknowledging the 5th message will cause all 5 messages to be acknowledged. @@ -370,7 +389,7 @@ You can specify schema-qualified user-defined types, but the property types and ## Message properties -All of the above-mentioned message types support setting and getting message properties. Before creating the actual message type, you must create the corresponding user-defined type for message properties. +All of the above-mentioned message types supports setting and getting message properties. Before creating the actual message type, you must create the corresponding user-defined type for message properties. This example shows how to create the user-defined type for message properties: @@ -387,21 +406,21 @@ All primitive types of message properties are supported. ### TextMessage -Text messages can be sent using the TextMessage interface. EDBTextMessageImpl is an implementation of TextMessage, but for most cases, you will be using the standard TextMessage. +Text messages can be sent using the `TextMessage` interface. `EDBTextMessageImpl` is an implementation of `TextMessage`, but for most cases, you will be using the standard `TextMessage`. Before using the text message, it is necessary to create a user-defined type for it. -Before using the text message, it is necessary to create a user-defined type for it. This example shows how to create the user-defined type for TextMessage: +This example shows how to create the user-defined messagetype for TextMessage: ```sql CREATE OR REPLACE TYPE AQ$_JMS_TEXT_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[], STRING_VALUE VARCHAR2(4000)); ``` -Once the user-defined type is created, you can then proceed to create the queue table using this type: +Once the user-defined type is created, you can create the queue table using this type. This example shows how to create the queue table using the above created user-defined message type. ```sql EXEC DBMS_AQADM.CREATE_QUEUE_TABLE (queue_table => 'MSG_QUEUE_TABLE', queue_payload_type => 'AQ$_JMS_TEXT_MESSAGE', comment => 'Message queue table'); ``` -After setting up the queue table, you can send and receive TextMessages using the standard procedure outlined in the Java code snippet: +After setting up the queue table, you can send and receive `TextMessages` using the standard procedure outlined in the Java code snippet: ```java MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); @@ -423,17 +442,17 @@ System.out.println(txtMsg.getStringProperty("myprop1")); ### BytesMessage -The BytesMessage is used to send a stream of bytes. EDBBytesMessageImpl is an implementation of BytesMessage, but in most cases, you will use the standard BytesMessage. Before using the bytes message, a user-defined type must be created. +The `BytesMessage` is used to send a stream of bytes. `EDBBytesMessageImpl` is an implementation of `BytesMessage`, but in most cases, you will use the standard `BytesMessage`. Before using the bytes message, a user-defined type must be created. -This example shows how to create the user-defined type for BytesMessage: +This example shows how to create the user-defined type for `BytesMessage`: ```sql CREATE OR REPLACE TYPE AQ$_JMS_BYTES_MESSAGE AS OBJECT (PROPERTIES AQ$_JMS_USERPROPERTY[], RAW_VALUE CLOB); ``` -Now, BytesMessage can be sent and received in the standard way. +Now, `BytesMessage` can be sent and received in the standard way. -This example shows how to create and use a BytesMessage in Java: +This example shows how to create and use a `BytesMessage` in Java: ```java MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); @@ -453,11 +472,11 @@ System.out.println(new String(bytes)); ### ObjectMessage -An ObjectMessage is used to send a serializable object as a message. EDBObjectMessageImpl is an implementation of ObjectMessage, but the standard ObjectMessage is most commonly used. +An `ObjectMessage` is used to send a serializable object as a message. `EDBObjectMessageImpl` is an implementation of `ObjectMessage`, but the standard `ObjectMessage` is most commonly used. -Before using the ObjectMessage, it is necessary to create the user-defined type for the object message. +Before using the `ObjectMessage`, it is necessary to create the user-defined type for the object message. -This example shows how to create the user-defined type for ObjectMessage: +This example shows how to create the user-defined type for `ObjectMessage`: ```sql CREATE OR REPLACE TYPE AQ$_JMS_OBJECT_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[], OBJECT_VALUE CLOB); @@ -500,7 +519,7 @@ public class Emp implements Serializable { } ``` -This example shows how to use ObjectMessage to send a message containing an object of this class: +This example shows how to use `ObjectMessage` to send a message containing an object of this class: ```java MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); @@ -527,13 +546,11 @@ System.out.println("Name: " + empBack.getName()); System.out.println("Role: " + empBack.getRole()); ``` - ## Message -A Message can be used to send a message with only properties and no body. EDBMessageImpl is an implementation of a Message, but you will most often use the standard Message. -Before using a message, it is required to create a user-defined type. +A `Message` can be used to send a message with only properties and no body. `EDBMessageImpl` is an implementation of a `Message`, but you will most often use the standard Message. Before using a `Message`, it is required to create a user-defined type. -This example shows how to create the user-defined type for Message: +This example shows how to create the user-defined type for `Message`: ```sql CREATE OR REPLACE TYPE AQ$_JMS_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[]); @@ -632,8 +649,8 @@ public class MyType extends com.edb.aq.UDTType { ``` !!!note -- To create a user-defined class, it must extend the com.edb.aq.operations.UDTType class and override the getParamValues() method. In this method, you should add the attribute values to an ArrayList in the same order as they appear in the CREATE TYPE SQL statement in the database. -- Additionally, make sure to use the annotation @CompareValue(0) with setter methods, as this specifies the order of methods when using the reflection API to reconstruct the object after dequeuing the message from the queue. +- To create a user-defined class, it must extend the `com.edb.aq.operations.UDTType` class and override the `getParamValues()` method. In this method, you should add the attribute values to an `ArrayList` in the same order as they appear in the CREATE TYPE SQL statement in the database. +- Additionally, make sure to use the annotation @CompareValue(0) with better methods, as this specifies the order of methods when using the reflection API to reconstruct the object after dequeuing the message from the queue. Failure to meet these requirements may result in errors. !!! @@ -662,8 +679,23 @@ System.out.println("Code: "+ myt.getCode()); System.out.println("Project: "+ myt.getProject()); System.out.println("Manager: "+ myt.getManager()); ``` +## Nested types + +This example shows how to use nested types in the user-defined types: + +```sql +CREATE OR REPLACE TYPE innermostcustom AS object (testing_field_1 text); + +CREATE OR REPLACE TYPE innercustom AS object (testing_field_1 text, innermost innermostcustom); + +CREATE OR REPLACE TYPE custom_type AS object (testing_field text, inner innercustom); +``` + +In this example, `custom_type` is using `innercustom` as another user-defined type that in turn is using `innermostcustom` user-defined type. EDB Postgres Advanced Server supports the nested types in such fashion, however it may have performance implications at certain level. EDB JMS API also provides flexibility to read such nested types at the cost of an added performance impact. + +To illustrate this using the EDB JMS API, you must first create the equivalent objects that represent nested custom types as shown below: -## InnermostCustom.java: +### InnermostCustom.java: ```java package mypackage; @@ -697,7 +729,7 @@ public class InnermostCustom extends UDTType { } ``` -## InnerCustom.java +### InnerCustom.java ```java package mypackage; @@ -742,7 +774,7 @@ public class InnerCustom extends UDTType { } ``` -## CustomType.java +### CustomType.java ```java package mypackage; diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/index.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/index.mdx index dd7122d3cbb..d278b1b4ec3 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/index.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/index.mdx @@ -1,7 +1,7 @@ --- title: "EDB JDBC Connector" directoryDefaults: - description: "EDB JDBC Connector Version 42.5.4.2 Documentation and release notes." + description: "EDB JDBC Connector Version 42.7.3.1 Documentation and release notes." navigation: - 01_jdbc_rel_notes - 02_requirements_overview From 0edae21c74ba76b4ba19df89ed2fd48c3ec94753 Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Wed, 18 Sep 2024 10:52:36 +0530 Subject: [PATCH 02/26] Added latest version to supported platforms page and Using advance queueing topic is split --- .../42.7.3.1/02_requirements_overview.mdx | 1 + .../05a_using_advanced_queueing/index.mdx | 24 ++ .../jms_application.mdx | 126 ++++++++ .../message_acknowledgement.mdx | 131 ++++++++ .../message_types.mdx | 206 +++++++++++++ .../non_standard_message.mdx | 282 ++++++++++++++++++ .../serverside_setup.mdx | 104 +++++++ 7 files changed, 874 insertions(+) create mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/index.mdx create mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx create mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx create mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx create mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/non_standard_message.mdx create mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx index d1933cd8c10..776a16c3dcc 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx @@ -19,6 +19,7 @@ This table lists the latest JDBC Connector versions and their supported correspo | JDBC Connector | EPAS16 | EPAS 15 | EPAS 14 | EPAS 13 | EPAS 12 | EPAS 11 | | ---------------------------------------------------------- | --------|-------- | ------- | ------- | ------- | ------- | +| [42.7.3.1](01_jdbc_rel_notes/jdbc_42.7.3.1_rel_notes) | Y | Y | Y | Y | Y | Y | | [42.5.4.2](01_jdbc_rel_notes/jdbc_42.5.4.2_rel_notes) | Y | Y | Y | Y | Y | Y | | [42.5.4.1](01_jdbc_rel_notes/jdbc_42.5.4.1_rel_notes) | N | Y | Y | Y | Y | Y | | [42.5.1.2](01_jdbc_rel_notes/jdbc_42.5.1.2_rel_notes) | N | Y | Y | Y | Y | Y | diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/index.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/index.mdx new file mode 100644 index 00000000000..e9f9111747c --- /dev/null +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/index.mdx @@ -0,0 +1,24 @@ +--- +title: "Using advanced queueing" +deepToC: true +indexdepth: 3 +navigation: +- serverside_setup +- jms_application +- message_acknowledgement +- message_types +- non_standard_message +--- + +!!! Tip "New Feature" + Advanced queueing is available in JDBC 42.3.2.1 and later. + +EDB Postgres Advanced Server advanced queueing provides message queueing and message processing for the EDB Postgres Advanced Server database. User-defined messages are stored in a queue, and a collection of queues is stored in a queue table. You must first create a queue table before creating a queue that depends on it. + +On the server side, procedures in the `DBMS_AQADM` package create and manage message queues and queue tables. Use the `DBMS_AQ` package to add or remove messages from a queue or register or unregister a SPL callback procedure. For more information about `DBMS_AQ` and `DBMS_AQADM`, see the [DBMS_AQ](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/02_dbms_aq/). + +On the client side, the application uses EDB-JDBC driver's JMS API to enqueue and dequeue message. + +## Enqueueing or dequeueing a message + +For more information about using EDB Postgres Advanced Server's advanced queueing functionality, see [Built-in packages](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/). \ No newline at end of file diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx new file mode 100644 index 00000000000..cc0eac608db --- /dev/null +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx @@ -0,0 +1,126 @@ +--- +title: "Setting up JMS application +--- + +After creating the queue table and queue for the message types and starting the queue, you can follow these steps to set up your JMS Application: + +1. Create a [Connection factory](#connection-factory). +1. Create a [Connection](#connection) using the connection factory. +1. Create a [Session](#session) using the connection. +1. Get the Queue from the session. +1. Create a [message producer](#message-producer) using the session and queue. + 1. Send messages. +1. Create a [message consumer](#message-consumer) using the session and queue. + 1. Receive messages. + + +### Connection factory + +The `Connection factory` is used to create connections. `EDBJmsConnectionFactory` is an implementation of `ConnectionFactory` and `QueueConnectionFactory`, used to create `Connection` and `QueueConnection`. A `Connection factory` can be created using one of the constructors of the `EDBJmsConnectionFactory` class. All three constructors can be used to create either a `ConnectionFactory` or `QueueConnectionFactory`. + +```java +//Constructor with connection related properties. +public EDBJmsConnectionFactory(String host, int port, String database, + String username, String password); +//Constructor with connection string, user name and password. +public EDBJmsConnectionFactory(String connectionString, + String username, String password); +//Constructor with SQL Connection. +public EDBJmsConnectionFactory(java.sql.Connection connection); +``` + +This example shows how to create a `ConnectionFactory` using an existing `java.sql.Connection`: + +```java +javax.jms.ConnectionFactory connFactory = new EDBJmsConnectionFactory(connection); +``` + +This example shows how to create a `QueueConnectionFactory` using a connection string, username, and password: + +```java +javax.jms.QueueConnectionFactory connFactory = new EDBJmsConnectionFactory + ("jdbc:edb//localhost:5444/edb", "enterprisedb", "edb"); +``` + +### Connection + +A `Connection` is a client's active connection that can be created from the `ConnectionFactory` and used to create sessions. `EDBJmsConnection` is an implementation of `Connection`, while `EDBJmsQueueConnection` is an implementation of `QueueConnection` and extends `EDBJmsConnection`. A `Connection` can be created using `ConnectionFactory`, while `QueueConnection` can be created from `QueueConnectionFactory`. + +This example shows how to create a `Connection` and a `QueueConnection`: + +```java +//Connection from ConnectionFactory. Assuming connFactory is ConnectionFactory. +javax.jms.Connection connection = connFactory.createConnection(); + +////Connection from QueueConnectionFactory. Assuming connFactory is QueueConnectionFactory. +javax.jms.QueueConnection queueConnection = connFactory.createQueueConnection(); +``` + +A connection must be started in order for the consumer to receive messages. On the other hand, a producer can send messages without starting the connection. + +This example shows how to start a connection: + +```java +queueConnection.start(); +``` + +A connection can be stopped at any time to cease receiving messages, and can be restarted when needed. However, a closed connection cannot be restarted. + +This example shows how to stop and close the connection: + +```java +queueConnection.stop(); +queueConnection.close(); +``` + +### Session + +The `Session` in EDBJms is used for creating producers and consumers, and for sending and receiving messages. `EDBJmsSession` implements the basic `Session` functionality, while `EDBJmsQueueSession` extends `EDBJmsSession` and implements `QueueSession`. A `Session` can be created from a `Connection`. + +This example shows how to create a `Session` and a `QueueSession`: + +```java +// Session +javax.jms.Session session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); +// QueueSession +javax.jms.QueueSession session = queueConnection.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); +``` + +A `Session` or `QueueSession` is also used to create queues. + +!!!note "Important" +In this context, "creating a queue" does not refer to physically creating the queue. As discussed earlier, the queue needs to be created and started as part of the server-side setup. In this context, creating a queue means getting the queue, related queue table, and payload type that have already been created. +!!! + +This example shows how to create a queue: + +```java +javax.jms.Queue queue = session.createQueue("MSG_QUEUE"); +``` + +### Message producer + +A `Message producer` is responsible for creating and sending messages. It is created using a session and queue. `EDBJmsMessageProducer` is an implementation of `MessageProducer`, but in most cases, you will be using the standard `MessageProducer`. + +This example shows how to create a message producer, create a message, and send it. Creating messages of different types will be discussed in the following sections. + +```java +javax.jms.MessageProducer messageProducer = session.createProducer(queue); + +javax.jms.Message msg = session.createMessage(); +msg.setStringProperty("myprop1", "test value 1"); + +messageProducer.send(msg); +``` + +### Message consumer + +A `Message consumer` is used to receive messages. It is created using a session and a queue. `EDBJmsMessageConsumer` is an implementation of `MessageConsumer`, but you will most often use the standard `MessageConsumer`. + +This example shows how to create a message consumer and receive a message: + +```java +javax.jms.MessageConsumer messageConsumer = session.createConsumer(queue); + +javax.jms.Message message = messageConsumer.receive(); +``` diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx new file mode 100644 index 00000000000..5fd3cbe28ce --- /dev/null +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx @@ -0,0 +1,131 @@ +--- +title: "Message acknowledgement" +deepToC: true +indexdepth: 3 +--- + +Acknowledgement of messages is controlled by the two arguments to the `createSession()` and `createQueueSession()` methods: + +```java +EDBJmsConnection.createSession(boolean transacted, int acknowledgeMode) + +EDBJmsQueueConnection.createQueueSession(boolean transacted, int acknowledgeMode) +``` + +If the first argument is true, it indicates that the session mode is transacted, and the second argument is ignored. However, if the first argument is false, then the second argument comes into play, and the client can specify different acknowledgment modes. + +These acknowledgment modes include, + +- Session.AUTO_ACKNOWLEDGE +- Session.CLIENT_ACKNOWLEDGE +- Session.DUPS_OK_ACKNOWLEDGE + +## Transacted session + +In transacted sessions, messages are both sent and received during a transaction. These messages are acknowledged by making an explicit call to `commit()`. If `rollback()` is called, all received messages will be marked as not acknowledged. + +A transacted session always has an active transaction. When a client calls the `commit()` or `rollback()` method, the current transaction is either committed or rolled back, and a new transaction is started. + +This example explains how the transacted session works: + +```java + MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); + + //Send a message in transacted session and commit it. + + //Send message + TextMessage msg1 = session.createTextMessage(); + String messageText1 = "Hello 1"; + msg1.setText(messageText1); + messageProducer.send(msg1); + + //Commit the transaction. + session.commit(); + + //Now we have one message in the queue. + + //Next, we want to send and receive in the same transaction. + + MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); + + //Send a Message in transaction. + TextMessage msg2 = session.createTextMessage(); + String messageText2 = "Hello 2"; + msg2.setText(messageText2); + messageProducer.send(msg2); + + //Receive message in the same transaction. There should be 1 message available. + Message message1 = messageConsumer.receive(); + TextMessage txtMsg1 = (TextMessage) message1; + + //Send another Message in transaction. + TextMessage msg3 = session.createTextMessage(); + String messageText3 = "Hello 3"; + msg3.setText(messageText3); + messageProducer.send(msg3); + + //Commit the transaction. + //This should remove the one message we sent initially and received above and send 2 messages. + session.commit(); + + //2 messages are in the queue so we can receive these 2 messages. + + //Receive 1 + Message message2 = messageConsumer.receive(); + TextMessage txtMsg2 = (TextMessage) message2; + + //Receive 2 + Message message3 = messageConsumer.receive(); + TextMessage txtMsg3 = (TextMessage) message3; + + //Commit the transaction. This will consume the two messages. + session.commit(); + + //Receive should fail now as there should be no messages available. + Message message4 = messageConsumer.receive(); + //message4 will be null here. +``` + +### AUTO_ACKNOWLEDGE mode + +If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.AUTO_ACKNOWLEDGE`, the messages are automatically acknowledged. + +### DUPS_OK_ACKNOWLEDGE mode + +This mode instructs the session to lazily acknowledge the message, and it is okay if some messages are redelivered. However, in EDB JMS, this option is implemented the same way as `Session.AUTO_ACKNOWLEDGE`, where messages will be acknowledged automatically. + +### CLIENT_ACKNOWLEDGE mode + +If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.CLIENT_ACKNOWLEDGE`, the messages are acknowledged when the client acknowledges the message by calling the `acknowledge()` method on a message. Acknowledging happens at the session level, and acknowledging one message will cause all the received messages to be acknowledged. + +For example, if we send 5 messages and then receive the 5 messages, acknowledging the 5th message will cause all 5 messages to be acknowledged. + +```java + MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); + + //Send 5 messages + for(int i=1; i<=5; i++) { + TextMessage msg = session.createTextMessage(); + String messageText = "Hello " + i; + msg.setText(messageText); + messageProducer.send(msg); + } + + MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); + + //Receive 4 + for(int i=1; i<=4; i++) { + Message message = messageConsumer.receive(); + TextMessage txtMsg = (TextMessage) message; + } + + //Receive the 5th message + Message message5 = messageConsumer.receive(); + TextMessage txtMsg5 = (TextMessage) message5; + + //Now acknowledge it and all the messages will be acknowledged. + txtMsg5.acknowledge(); + + //Try to receive again. This should return null as there is no message available. + Message messageAgain = messageConsumer.receive(); +``` \ No newline at end of file diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx new file mode 100644 index 00000000000..4d83c548d2c --- /dev/null +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx @@ -0,0 +1,206 @@ +--- +title: "Message types" +deepToC: true +indexdepth: 3 +--- + +EDB-JDBC JMS API supports the following message types and can be used in a standard way: + +| Message type | JMS type | +|------------------------|-------------------------| +| aq$_jms_message | javax.jms.Message | +| aq$_jms_text_message | javax.jms.TextMessage | +| aq$_jms_bytes_message | javax.jms.BytesMessage | +| aq$_jms_object_message | javax.jms.ObjectMessage | + +Please note that the corresponding payload types (user-defined types) are not pre-defined and must be created by the user before configuring the queue table. This is discussed in the upcoming sections. + +You can specify schema-qualified user-defined types, but the property types and message types must be in the same schema. + +## Message properties + +All of the above-mentioned message types supports setting and getting message properties. Before creating the actual message type, you must create the corresponding user-defined type for message properties. + +This example shows how to create the user-defined type for message properties: + +```sql +CREATE OR REPLACE TYPE AQ$_JMS_USERPROPERTY +AS object +( + NAME VARCHAR2(100), + VALUE VARCHAR2(2000) +); +``` + +All primitive types of message properties are supported. + +### TextMessage + +Text messages can be sent using the `TextMessage` interface. `EDBTextMessageImpl` is an implementation of `TextMessage`, but for most cases, you will be using the standard `TextMessage`. Before using the text message, it is necessary to create a user-defined type for it. + +This example shows how to create the user-defined messagetype for TextMessage: + +```sql +CREATE OR REPLACE TYPE AQ$_JMS_TEXT_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[], STRING_VALUE VARCHAR2(4000)); +``` + +Once the user-defined type is created, you can create the queue table using this type. This example shows how to create the queue table using the above created user-defined message type. + +```sql +EXEC DBMS_AQADM.CREATE_QUEUE_TABLE (queue_table => 'MSG_QUEUE_TABLE', queue_payload_type => 'AQ$_JMS_TEXT_MESSAGE', comment => 'Message queue table'); +``` + +After setting up the queue table, you can send and receive `TextMessages` using the standard procedure outlined in the Java code snippet: + +```java +MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); +// Create text message +TextMessage msg = session.createTextMessage(); +String messageText = "Hello there!"; +msg.setText(messageText); +msg.setStringProperty("myprop1", "test value 1"); +// Send message +messageProducer.send(msg); + +MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); +// Receive Message +Message message = messageConsumer.receive(); +TextMessage txtMsg = (TextMessage) message; +System.out.println(txtMsg.getText()); +System.out.println(txtMsg.getStringProperty("myprop1")); +``` + +### BytesMessage + +The `BytesMessage` is used to send a stream of bytes. `EDBBytesMessageImpl` is an implementation of `BytesMessage`, but in most cases, you will use the standard `BytesMessage`. Before using the bytes message, a user-defined type must be created. + +This example shows how to create the user-defined type for `BytesMessage`: + +```sql +CREATE OR REPLACE TYPE AQ$_JMS_BYTES_MESSAGE AS OBJECT (PROPERTIES AQ$_JMS_USERPROPERTY[], RAW_VALUE CLOB); +``` + +Now, `BytesMessage` can be sent and received in the standard way. + +This example shows how to create and use a `BytesMessage` in Java: + +```java +MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); +BytesMessage msg = session.createBytesMessage(); +String messageText = "Hello there!"; +msg.writeBytes(messageText.getBytes()); +messageProducer.send(msg); + +MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); +Message message = messageConsumer.receive(); +BytesMessage byteMsg = (BytesMessage) message; +byteMsg.reset(); +byte[] bytes = new byte[(int) byteMsg.getBodyLength()]; +byteMsg.readBytes(bytes); +System.out.println(new String(bytes)); +``` + +### ObjectMessage + +An `ObjectMessage` is used to send a serializable object as a message. `EDBObjectMessageImpl` is an implementation of `ObjectMessage`, but the standard `ObjectMessage` is most commonly used. + +Before using the `ObjectMessage`, it is necessary to create the user-defined type for the object message. + +This example shows how to create the user-defined type for `ObjectMessage`: + +```sql +CREATE OR REPLACE TYPE AQ$_JMS_OBJECT_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[], OBJECT_VALUE CLOB); +``` + +For example we have the following serializable Java class: + +```java +import java.io.Serializable; + +public class Emp implements Serializable { + private int id; + private String name; + private String role; + + // Getter and setter methods + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } +} +``` + +This example shows how to use `ObjectMessage` to send a message containing an object of this class: + +```java +MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); + +// Create object message +ObjectMessage msg = session.createObjectMessage(); +Emp emp = new Emp(); +emp.setId(1); +emp.setName("Joe"); +emp.setRole("Manager"); +msg.setObject(emp); + +// Send message +messageProducer.send(msg); + +MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); + +// Receive Message +Message message = messageConsumer.receive(); +ObjectMessage objMsg = (ObjectMessage) message; +Emp empBack = (Emp) objMsg.getObject(); +System.out.println("ID: " + empBack.getId()); +System.out.println("Name: " + empBack.getName()); +System.out.println("Role: " + empBack.getRole()); +``` + +## Message + +A `Message` can be used to send a message with only properties and no body. `EDBMessageImpl` is an implementation of a `Message`, but you will most often use the standard Message. Before using a `Message`, it is required to create a user-defined type. + +This example shows how to create the user-defined type for `Message`: + +```sql +CREATE OR REPLACE TYPE AQ$_JMS_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[]); +``` + +This example shows how to send a message that contains only properties and no body: + +```java +MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); +// Create message. +Message msg = session.createMessage(); +msg.setStringProperty("myprop1", "test value 1"); +msg.setStringProperty("myprop2", "test value 2"); +msg.setStringProperty("myprop3", "test value 3"); +// Send message +messageProducer.send(msg); +MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); +// Receive Message +message = messageConsumer.receive(); +System.out.println("myprop1: " + message.getStringProperty("myprop1")); +System.out.println("myprop2: " + message.getStringProperty("myprop2")); +System.out.println("myprop3: " + message.getStringProperty("myprop3")); +``` diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/non_standard_message.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/non_standard_message.mdx new file mode 100644 index 00000000000..e98530f028c --- /dev/null +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/non_standard_message.mdx @@ -0,0 +1,282 @@ +--- +title: "Non-standard message" +deepToC: true +indexdepth: 3 +--- + +EDB-JDBC JMS allows users to send and receive non-standard messages that are fully controlled by the API user. These messages do not support the setting and getting of properties. The process involves creating a user-defined type and setting it as the payload for the queue table. + +This example shows how to create a Java Bean corresponding to the type you created: + +```java +package mypackage; +import com.edb.jms.common.CompareValue; +import java.util.ArrayList; +public class MyType extends com.edb.aq.UDTType { + private Integer code; + private String project; + private String manager; + public MyType() { + } + /** + * @param code the code to set + */ + @CompareValue(0) + public void setCode(Integer code) { + this.code = code; + } + /** + * @return the code + */ + public Integer getCode() { + return code; + } + /** + * @param project the project to set + */ + @CompareValue(1) + public void setProject(String project) { + this.project = project; + } + /** + * @return the project + */ + public String getProject() { + return project; + } + @CompareValue(2) + public void setManager(String manager) { + this.manager = manager; + } + public String getManager() { + return manager; + } + public String valueOf() { + StringBuilder sql = new StringBuilder("CREATE TYPE "); + sql.append(getName() + " "); + sql.append("AS ("); + sql.append("code int, "); + sql.append("project TEXT);"); + return sql.toString(); + } + /** + * Override this method and call getter methods in the same order as in CREATE TYPE statement. + * CREATE OR REPLACE TYPE mytype AS object (code int, project text, manager varchar(10)) + * @return object array containing parameters. + */ + @Override + public Object[] getParamValues() { + ArrayList params = new ArrayList<>(); + params.add(getCode()); + params.add(getProject()); + params.add(getManager()); + return params.toArray(); + } +} +``` + +!!!note +- To create a user-defined class, it must extend the `com.edb.aq.operations.UDTType` class and override the `getParamValues()` method. In this method, you should add the attribute values to an `ArrayList` in the same order as they appear in the CREATE TYPE SQL statement in the database. +- Additionally, make sure to use the annotation @CompareValue(0) with better methods, as this specifies the order of methods when using the reflection API to reconstruct the object after dequeuing the message from the queue. + +Failure to meet these requirements may result in errors. +!!! + +This example shows how to send an object of this class as a message: + +```java +messageProducer = (EDBJmsMessageProducer) session.createProducer(queue); + MyType udtType1 = new MyType(); + udtType1.setProject("Test Project"); + udtType1.setManager("Joe"); + udtType1.setCode(321); + udtType1.setName("mytype"); //type name used in "CREATE TYPE" + messageProducer.send(udtType1); +``` + +This example shows how to receive this object as a message: + +```java +messageConsumer = (EDBJmsMessageConsumer) session.createConsumer(queue); + +Message message = messageConsumer.receive(); + +MyType myt = (MyType) message; +System.out.println("Code: "+ myt.getCode()); +System.out.println("Project: "+ myt.getProject()); +System.out.println("Manager: "+ myt.getManager()); +``` +## Nested types + +This example shows how to use nested types in the user-defined types: + +```sql +CREATE OR REPLACE TYPE innermostcustom AS object (testing_field_1 text); + +CREATE OR REPLACE TYPE innercustom AS object (testing_field_1 text, innermost innermostcustom); + +CREATE OR REPLACE TYPE custom_type AS object (testing_field text, inner innercustom); +``` + +In this example, `custom_type` is using `innercustom` as another user-defined type that in turn is using `innermostcustom` user-defined type. EDB Postgres Advanced Server supports the nested types in such fashion, however it may have performance implications at certain level. EDB JMS API also provides flexibility to read such nested types at the cost of an added performance impact. + +To illustrate this using the EDB JMS API, you must first create the equivalent objects that represent nested custom types as shown below: + +### InnermostCustom.java + +```java +package mypackage; + +import com.edb.aq.UDTType; +import com.edb.jms.common.CompareValue; + +import java.util.ArrayList; + +public class InnermostCustom extends UDTType { + + public InnermostCustom() { + } + + private String testing_field_1; + + public String getTesting_field_1() { + return testing_field_1; + } + + @CompareValue(0) + public void setTesting_field_1(String testing_field_1) { + this.testing_field_1 = testing_field_1; + } + @Override + public Object[] getParamValues(){ + ArrayList params = new ArrayList(); + params.add(getTesting_field_1()); + return params.toArray(); + } +} +``` + +### InnerCustom.java + +```java +package mypackage; + +import com.edb.aq.UDTType; +import com.edb.jms.common.CompareValue; + +import java.util.ArrayList; + +public class InnerCustom extends UDTType { + + public InnerCustom() { + } + + private String testing_field_1; + private InnermostCustom innermostCustom; + + public String getTesting_field_1() { + return testing_field_1; + } + + @CompareValue(0) + public void setTesting_field_1(String testing_field_1) { + this.testing_field_1 = testing_field_1; + } + + public InnermostCustom getInnermostCustom() { + return innermostCustom; + } + + @CompareValue(1) + public void setInnermostCustom(InnermostCustom innermostCustom) { + this.innermostCustom = innermostCustom; + } + @Override + public Object[] getParamValues(){ + ArrayList params = new ArrayList(); + params.add(getTesting_field_1()); + params.add(getInnermostCustom()); + return params.toArray(); + } +} +``` + +### CustomType.java + +```java +package mypackage; + +import com.edb.aq.UDTType; +import com.edb.jms.common.CompareValue; + +import java.util.ArrayList; + +public class CustomType extends UDTType { + + private String testing_field; + private InnerCustom innerCustom; + + public String getTesting_field() { + return testing_field; + } + + @CompareValue(0) + public void setTesting_field(String testing_field) { + this.testing_field = testing_field; + } + + public InnerCustom getInnerCustom() { + return innerCustom; + } + + @CompareValue(1) + public void setInnerCustom(InnerCustom innerCustom) { + this.innerCustom = innerCustom; + } + + public CustomType() { + + } + + public Object[] getParamValues(){ + ArrayList params = new ArrayList(); + params.add(getTesting_field()); + params.add(getInnerCustom()); + return params.toArray(); + } +} +``` + +This example shows how to read such nested types: + +```java + EDBJmsMessageProducer messageProducer = (EDBJmsMessageProducer) session.createProducer(queue_1); + + InnermostCustom innermostCustom = new InnermostCustom(); + innermostCustom.setTesting_field_1("Innermost set"); + innermostCustom.setName("innermostCustom"); + + InnerCustom innerCustom = new InnerCustom(); + innerCustom.setTesting_field_1("Inner set"); + innerCustom.setInnermostCustom(innermostCustom); + innerCustom.setName("innercustom"); + + CustomType customType = new CustomType(); + customType.setTesting_field("EDB"); + customType.setInnerCustom(innerCustom); + customType.setName("custom_type"); + + messageProducer.send(customType); + + EDBJmsMessageConsumer messageConsumer = (EDBJmsMessageConsumer) session.createConsumer(queue_1); + + Message message = messageConsumer.receive(); + + CustomType myType = (CustomType) message; + InnerCustom innerCustom_1 = myType.getInnerCustom(); + InnermostCustom innermostCustom1 = innerCustom_1.getInnermostCustom(); + + System.out.println("Outer type test field: " + myType.getTesting_field()); + System.out.println("Inner type test field: " + innerCustom_1.getTesting_field_1()); + System.out.println("Most Inner type test field: " + innermostCustom1.getTesting_field_1()); +``` \ No newline at end of file diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx new file mode 100644 index 00000000000..0e109221c85 --- /dev/null +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx @@ -0,0 +1,104 @@ +--- +title: Server-side setup +deepToC: true +indexdepth: 3 +--- + +To use advanced queueing functionality on your JMS-based Java application perform following steps in EDB-PSQL or EDB-JDBC: + +1. Create a user-defined message type, which may be one of the standard JMS message types. However, EDB-JDBC also supports any user-defined message types. These [message types](message_types.mdx) will be covered in detail in the upcoming sections. +2. Create a queue table specifying the payload type. This type will typically be the one created in step 1. +3. Create a queue using the queue table created in the previous step. +4. Start the queue on the database server. +5. You have the option to use either [EDB-PSQL](#using-edb-psql) or [EDB-JDBC JMS API](#using-edb-jdbc-jms-api) in your Java application. + +## Using EDB-PSQL + +Invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Use the SPL commands in EDB-PSQL to: + +- [Create a user-defined type](#create-a-user-defined-type) +- [Create the queue table](#create-a-user-defined-type) +- [Create the queue](#create-the-queue) +- [Start the queue](#start-the-queue) + +### Create a user-defined type + +To specify a RAW data type, create a user-defined type. + +This example shows how to create a user-defined type named as `mytype`: + +```sql +CREATE OR REPLACE TYPE mytype AS (code INT, project TEXT, manager VARCHAR(10)); +``` + +### Create the queue table + +A queue table can hold multiple queues with the same payload type. + +This example shows how to create a queue table named `MSG_QUEUE_TABLE`: + +```sql +EXEC DBMS_AQADM.CREATE_QUEUE_TABLE + (queue_table => 'MSG_QUEUE_TABLE', + queue_payload_type => 'mytype', + comment => 'Message queue table'); +END; +``` + +### Create the queue + +This example shows how to create a queue named `MSG_QUEUE` in the table `MSG_QUEUE_TABLE`: + +```sql +EXEC DBMS_AQADM.CREATE_QUEUE + (queue_name => 'MSG_QUEUE', + queue_table => 'MSG_QUEUE_TABLE', + comment => 'This queue contains pending messages.'); +``` + +### Start the queue + +Once the queue is created, start the queue. + +This example shows how to start a queue in the database: + +```sql +EXEC DBMS_AQADM.START_QUEUE(queue_name => 'MSG_QUEUE'); +commit; +``` + +## Using EDB-JDBC JMS API + +!!!note "Tip" +The following sequence of steps is required only if you want to create message types, queue table and queue programmatically. If the message types, queue table, and queue are created using EDB-PSQL then you can use the standard JMS API. +!!! + +The following JMS API calls perform the same steps performed using EDB-PSQL to: + +- Connect to the EDB Postgres Advanced Server database +- Create the user-defined type +- Create the queue table and queue +- Start the queue + +```java +edbJmsFact = new EDBJmsConnectionFactory("localhost", 5444, "edb", "edb", "edb"); + +conn = (EDBJmsQueueConnection) edbJmsFact.createQueueConnection(); + +session = (EDBJmsQueueSession) conn.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE); + +String sql = "CREATE OR REPLACE TYPE mytype AS (code int, project TEXT);"; +UDTType udtType = new UDTType(conn.getConn(), sql, "mytype"); +Operation operation = new UDTTypeOperation(udtType); +operation.execute(); + +queueTable = session.createQueueTable(conn.getConn(), "MSG_QUEUE_TABLE", "mytype", "Message queue table"); + +Queue queue1 = new Queue(conn.getConn(), "MSG_QUEUE", "MSG_QUEUE_TABLE", "Message Queue"); +operation = new QueueOperation(queue1); +operation.execute(); + +queue = (EDBJmsQueue) session.createQueue("MSG_QUEUE"); +queue.setEdbQueueTbl(queueTable); + +queue.start(); \ No newline at end of file From 814fbf12a1cf0f42bd577bfe40fd02be8652478b Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:04:05 +0530 Subject: [PATCH 03/26] minor fixes --- .../05a_using_advanced_queueing/jms_application.mdx | 8 +++----- .../05a_using_advanced_queueing/serverside_setup.mdx | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx index cc0eac608db..28acf598fd6 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/jms_application.mdx @@ -1,5 +1,5 @@ --- -title: "Setting up JMS application +title: "Setting up JMS application" --- After creating the queue table and queue for the message types and starting the queue, you can follow these steps to set up your JMS Application: @@ -8,10 +8,8 @@ After creating the queue table and queue for the message types and starting the 1. Create a [Connection](#connection) using the connection factory. 1. Create a [Session](#session) using the connection. 1. Get the Queue from the session. -1. Create a [message producer](#message-producer) using the session and queue. - 1. Send messages. -1. Create a [message consumer](#message-consumer) using the session and queue. - 1. Receive messages. +1. Create a [message producer](#message-producer) using the session and queue to send messages. +1. Create a [message consumer](#message-consumer) using the session and queue to receive messages. ### Connection factory diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx index 0e109221c85..6ab04a75e87 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/serverside_setup.mdx @@ -1,5 +1,5 @@ --- -title: Server-side setup +title: "Server-side setup" deepToC: true indexdepth: 3 --- From 11acfff9d2260d86c9c9eb39fed312187b9281f9 Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Wed, 18 Sep 2024 11:52:39 +0530 Subject: [PATCH 04/26] Updated the heading levels as per suggestion from Moazzum --- .../05a_using_advanced_queueing/message_acknowledgement.mdx | 6 +++--- .../42.7.3.1/05a_using_advanced_queueing/message_types.mdx | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx index 5fd3cbe28ce..e711f536485 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_acknowledgement.mdx @@ -86,15 +86,15 @@ This example explains how the transacted session works: //message4 will be null here. ``` -### AUTO_ACKNOWLEDGE mode +## AUTO_ACKNOWLEDGE mode If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.AUTO_ACKNOWLEDGE`, the messages are automatically acknowledged. -### DUPS_OK_ACKNOWLEDGE mode +## DUPS_OK_ACKNOWLEDGE mode This mode instructs the session to lazily acknowledge the message, and it is okay if some messages are redelivered. However, in EDB JMS, this option is implemented the same way as `Session.AUTO_ACKNOWLEDGE`, where messages will be acknowledged automatically. -### CLIENT_ACKNOWLEDGE mode +## CLIENT_ACKNOWLEDGE mode If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.CLIENT_ACKNOWLEDGE`, the messages are acknowledged when the client acknowledges the message by calling the `acknowledge()` method on a message. Acknowledging happens at the session level, and acknowledging one message will cause all the received messages to be acknowledged. diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx index 4d83c548d2c..08796ff926a 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing/message_types.mdx @@ -34,7 +34,7 @@ AS object All primitive types of message properties are supported. -### TextMessage +## TextMessage Text messages can be sent using the `TextMessage` interface. `EDBTextMessageImpl` is an implementation of `TextMessage`, but for most cases, you will be using the standard `TextMessage`. Before using the text message, it is necessary to create a user-defined type for it. @@ -70,7 +70,7 @@ System.out.println(txtMsg.getText()); System.out.println(txtMsg.getStringProperty("myprop1")); ``` -### BytesMessage +## BytesMessage The `BytesMessage` is used to send a stream of bytes. `EDBBytesMessageImpl` is an implementation of `BytesMessage`, but in most cases, you will use the standard `BytesMessage`. Before using the bytes message, a user-defined type must be created. @@ -100,7 +100,7 @@ byteMsg.readBytes(bytes); System.out.println(new String(bytes)); ``` -### ObjectMessage +## ObjectMessage An `ObjectMessage` is used to send a serializable object as a message. `EDBObjectMessageImpl` is an implementation of `ObjectMessage`, but the standard `ObjectMessage` is most commonly used. From 94b497286aec3a73bc256f8c37f537f45a9bb1d7 Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:27:19 +0530 Subject: [PATCH 05/26] minor fix --- .../docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx index 776a16c3dcc..35ca32891ad 100644 --- a/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx +++ b/product_docs/docs/jdbc_connector/42.7.3.1/02_requirements_overview.mdx @@ -19,7 +19,7 @@ This table lists the latest JDBC Connector versions and their supported correspo | JDBC Connector | EPAS16 | EPAS 15 | EPAS 14 | EPAS 13 | EPAS 12 | EPAS 11 | | ---------------------------------------------------------- | --------|-------- | ------- | ------- | ------- | ------- | -| [42.7.3.1](01_jdbc_rel_notes/jdbc_42.7.3.1_rel_notes) | Y | Y | Y | Y | Y | Y | +| [42.7.3.1](01_jdbc_rel_notes/jdbc_42.7.3.1_rel_notes) | Y | Y | Y | Y | Y | N | | [42.5.4.2](01_jdbc_rel_notes/jdbc_42.5.4.2_rel_notes) | Y | Y | Y | Y | Y | Y | | [42.5.4.1](01_jdbc_rel_notes/jdbc_42.5.4.1_rel_notes) | N | Y | Y | Y | Y | Y | | [42.5.1.2](01_jdbc_rel_notes/jdbc_42.5.1.2_rel_notes) | N | Y | Y | Y | Y | Y | From 812fbdd79e70096203631f837b21cc588a91cced Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Thu, 19 Sep 2024 10:28:12 +0530 Subject: [PATCH 06/26] removed old file as the topic is splitted with sub-topics --- .../42.7.3.1/05a_using_advanced_queueing.mdx | 855 ------------------ 1 file changed, 855 deletions(-) delete mode 100644 product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx diff --git a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx b/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx deleted file mode 100644 index c463afbf09e..00000000000 --- a/product_docs/docs/jdbc_connector/42.7.3.1/05a_using_advanced_queueing.mdx +++ /dev/null @@ -1,855 +0,0 @@ ---- -title: "Using advanced queueing" -deepToC: true -indexdepth: 3 ---- - -!!! Tip "New Feature" - Advanced queueing is available in JDBC 42.3.2.1 and later. - -EDB Postgres Advanced Server advanced queueing provides message queueing and message processing for the EDB Postgres Advanced Server database. User-defined messages are stored in a queue, and a collection of queues is stored in a queue table. You must first create a queue table before creating a queue that depends on it. - -On the server side, procedures in the `DBMS_AQADM` package create and manage message queues and queue tables. Use the `DBMS_AQ` package to add or remove messages from a queue or register or unregister a SPL callback procedure. For more information about `DBMS_AQ` and `DBMS_AQADM`, see the [DBMS_AQ](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/02_dbms_aq/). - -On the client side, the application uses EDB-JDBC driver's JMS API to enqueue and dequeue message. - -## Enqueueing or dequeueing a message - -For more information about using EDB Postgres Advanced Server's advanced queueing functionality, see [Built-in packages](/epas/latest/reference/oracle_compatibility_reference/epas_compat_bip_guide/03_built-in_packages/). - -## Server-side setup - -To use advanced queueing functionality on your JMS-based Java application perform following steps in EDB-PSQL or EDB-JDBC: - -1. Create a user-defined message type, which may be one of the standard JMS message types. However, EDB-JDBC also supports any user-defined message types. These [message types](#message-types) will be covered in detail in the upcoming sections. -1. Create a queue table specifying the payload type. This type will typically be the one created in step 1. -1. Create a queue using the queue table created in the previous step. -1. Start the queue on the database server. -1. You have the option to use either [EDB-PSQL](#using-edb-psql) or [EDB-JDBC JMS API](#using-edb-jdbc-jms-api) in your Java application. - -### Using EDB-PSQL - -Invoke EDB-PSQL and connect to the EDB Postgres Advanced Server host database. Use the SPL commands in EDB-PSQL to: - -- [Create a user-defined type](#create-a-user-defined-type) -- [Create the queue table](#create-a-user-defined-type) -- [Create the queue](#create-the-queue) -- [Start the queue](#start-the-queue) - -#### Create a user-defined type** - -To specify a RAW data type, create a user-defined type. - -This example shows how to create a user-defined type named as `mytype`: - -```sql -CREATE OR REPLACE TYPE mytype AS (code INT, project TEXT, manager VARCHAR(10)); -``` - -#### Create the queue table - -A queue table can hold multiple queues with the same payload type. - -This example shows how to create a queue table named `MSG_QUEUE_TABLE`: - -```sql -EXEC DBMS_AQADM.CREATE_QUEUE_TABLE - (queue_table => 'MSG_QUEUE_TABLE', - queue_payload_type => 'mytype', - comment => 'Message queue table'); -END; -``` - -#### Create the queue - -This example shows how to create a queue named `MSG_QUEUE` in the table `MSG_QUEUE_TABLE`: - -```sql -EXEC DBMS_AQADM.CREATE_QUEUE - (queue_name => 'MSG_QUEUE', - queue_table => 'MSG_QUEUE_TABLE', - comment => 'This queue contains pending messages.'); -``` - -#### Start the queue - -Once the queue is created, start the queue. - -This example shows how to start a queue in the database: - -```sql -EXEC DBMS_AQADM.START_QUEUE(queue_name => 'MSG_QUEUE'); -commit; -``` - -### Using EDB-JDBC JMS API - -!!!note "Tip" -The following sequence of steps is required only if you want to create message types, queue table and queue programmatically. If the message types, queue table, and queue are created using EDB-PSQL then you can use the standard JMS API. -!!! - -The following JMS API calls perform the same steps performed using EDB-PSQL to: - -- Connect to the EDB Postgres Advanced Server database -- Create the user-defined type -- Create the queue table and queue -- Start the queue - -```java -edbJmsFact = new EDBJmsConnectionFactory("localhost", 5444, "edb", "edb", "edb"); - -conn = (EDBJmsQueueConnection) edbJmsFact.createQueueConnection(); - -session = (EDBJmsQueueSession) conn.createQueueSession(true, Session.CLIENT_ACKNOWLEDGE); - -String sql = "CREATE OR REPLACE TYPE mytype AS (code int, project TEXT);"; -UDTType udtType = new UDTType(conn.getConn(), sql, "mytype"); -Operation operation = new UDTTypeOperation(udtType); -operation.execute(); - -queueTable = session.createQueueTable(conn.getConn(), "MSG_QUEUE_TABLE", "mytype", "Message queue table"); - -Queue queue1 = new Queue(conn.getConn(), "MSG_QUEUE", "MSG_QUEUE_TABLE", "Message Queue"); -operation = new QueueOperation(queue1); -operation.execute(); - -queue = (EDBJmsQueue) session.createQueue("MSG_QUEUE"); -queue.setEdbQueueTbl(queueTable); - -queue.start(); -``` - -## Setting up JMS application - -After creating the queue table and queue for the message types and starting the queue, you can follow these steps to set up your JMS Application: - -1. Create a [Connection factory](#connection-factory). -1. Create a [Connection](#connection) using the connection factory. -1. Create a [Session](#session) using the connection. -1. Get the Queue from the session. -1. Create a [message producer](#message-producer) using the session and queue. - 1. Send messages. -1. Create a [message consumer](#message-consumer) using the session and queue. - 1. Receive messages. - - -### Connection factory - -The `Connection factory` is used to create connections. `EDBJmsConnectionFactory` is an implementation of `ConnectionFactory` and `QueueConnectionFactory`, used to create `Connection` and `QueueConnection`. A `Connection factory` can be created using one of the constructors of the `EDBJmsConnectionFactory` class. All three constructors can be used to create either a `ConnectionFactory` or `QueueConnectionFactory`. - -```java -//Constructor with connection related properties. -public EDBJmsConnectionFactory(String host, int port, String database, - String username, String password); -//Constructor with connection string, user name and password. -public EDBJmsConnectionFactory(String connectionString, - String username, String password); -//Constructor with SQL Connection. -public EDBJmsConnectionFactory(java.sql.Connection connection); -``` - -This example shows how to create a `ConnectionFactory` using an existing `java.sql.Connection`: - -```java -javax.jms.ConnectionFactory connFactory = new EDBJmsConnectionFactory(connection); -``` - -This example shows how to create a `QueueConnectionFactory` using a connection string, username, and password: - -```java -javax.jms.QueueConnectionFactory connFactory = new EDBJmsConnectionFactory - ("jdbc:edb//localhost:5444/edb", "enterprisedb", "edb"); -``` - -### Connection - -A `Connection` is a client's active connection that can be created from the `ConnectionFactory` and used to create sessions. `EDBJmsConnection` is an implementation of `Connection`, while `EDBJmsQueueConnection` is an implementation of `QueueConnection` and extends `EDBJmsConnection`. A `Connection` can be created using `ConnectionFactory`, while `QueueConnection` can be created from `QueueConnectionFactory`. - -This example shows how to create a `Connection` and a `QueueConnection`: - -```java -//Connection from ConnectionFactory. Assuming connFactory is ConnectionFactory. -javax.jms.Connection connection = connFactory.createConnection(); - -////Connection from QueueConnectionFactory. Assuming connFactory is QueueConnectionFactory. -javax.jms.QueueConnection queueConnection = connFactory.createQueueConnection(); -``` - -A connection must be started in order for the consumer to receive messages. On the other hand, a producer can send messages without starting the connection. - -This example shows how to start a connection: - -```java -queueConnection.start(); -``` - -A connection can be stopped at any time to cease receiving messages, and can be restarted when needed. However, a closed connection cannot be restarted. - -This example shows how to stop and close the connection: - -```java -queueConnection.stop(); -queueConnection.close(); -``` - -### Session - -The `Session` in EDBJms is used for creating producers and consumers, and for sending and receiving messages. `EDBJmsSession` implements the basic `Session` functionality, while `EDBJmsQueueSession` extends `EDBJmsSession` and implements `QueueSession`. A `Session` can be created from a `Connection`. - -This example shows how to create a `Session` and a `QueueSession`: - -```java -// Session -javax.jms.Session session = connection.createSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); -// QueueSession -javax.jms.QueueSession session = queueConnection.createQueueSession(false, javax.jms.Session.AUTO_ACKNOWLEDGE); -``` - -A `Session` or `QueueSession` is also used to create queues. - -!!!note "Important" -In this context, "creating a queue" does not refer to physically creating the queue. As discussed earlier, the queue needs to be created and started as part of the server-side setup. In this context, creating a queue means getting the queue, related queue table, and payload type that have already been created. -!!! - -This example shows how to create a queue: - -```java -javax.jms.Queue queue = session.createQueue("MSG_QUEUE"); -``` - -### Message producer - -A `Message producer` is responsible for creating and sending messages. It is created using a session and queue. `EDBJmsMessageProducer` is an implementation of `MessageProducer`, but in most cases, you will be using the standard `MessageProducer`. - -This example shows how to create a message producer, create a message, and send it. Creating messages of different types will be discussed in the following sections. - -```java -javax.jms.MessageProducer messageProducer = session.createProducer(queue); - -javax.jms.Message msg = session.createMessage(); -msg.setStringProperty("myprop1", "test value 1"); - -messageProducer.send(msg); -``` - -### Message consumer - -A `Message consumer` is used to receive messages. It is created using a session and a queue. `EDBJmsMessageConsumer` is an implementation of `MessageConsumer`, but you will most often use the standard `MessageConsumer`. - -This example shows how to create a message consumer and receive a message: - -```java -javax.jms.MessageConsumer messageConsumer = session.createConsumer(queue); - -javax.jms.Message message = messageConsumer.receive(); -``` - -### Message acknowledgement - -Acknowledgement of messages is controlled by the two arguments to the `createSession()` and `createQueueSession()` methods: - -```java -EDBJmsConnection.createSession(boolean transacted, int acknowledgeMode) - -EDBJmsQueueConnection.createQueueSession(boolean transacted, int acknowledgeMode) -``` - -If the first argument is true, it indicates that the session mode is transacted, and the second argument is ignored. However, if the first argument is false, then the second argument comes into play, and the client can specify different acknowledgment modes. - -These acknowledgment modes include, - -- Session.AUTO_ACKNOWLEDGE -- Session.CLIENT_ACKNOWLEDGE -- Session.DUPS_OK_ACKNOWLEDGE - -## Transacted session - -In transacted sessions, messages are both sent and received during a transaction. These messages are acknowledged by making an explicit call to `commit()`. If `rollback()` is called, all received messages will be marked as not acknowledged. - -A transacted session always has an active transaction. When a client calls the `commit()` or `rollback()` method, the current transaction is either committed or rolled back, and a new transaction is started. - -This example explains how the transacted session works: - -```java - MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); - - //Send a message in transacted session and commit it. - - //Send message - TextMessage msg1 = session.createTextMessage(); - String messageText1 = "Hello 1"; - msg1.setText(messageText1); - messageProducer.send(msg1); - - //Commit the transaction. - session.commit(); - - //Now we have one message in the queue. - - //Next, we want to send and receive in the same transaction. - - MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); - - //Send a Message in transaction. - TextMessage msg2 = session.createTextMessage(); - String messageText2 = "Hello 2"; - msg2.setText(messageText2); - messageProducer.send(msg2); - - //Receive message in the same transaction. There should be 1 message available. - Message message1 = messageConsumer.receive(); - TextMessage txtMsg1 = (TextMessage) message1; - - //Send another Message in transaction. - TextMessage msg3 = session.createTextMessage(); - String messageText3 = "Hello 3"; - msg3.setText(messageText3); - messageProducer.send(msg3); - - //Commit the transaction. - //This should remove the one message we sent initially and received above and send 2 messages. - session.commit(); - - //2 messages are in the queue so we can receive these 2 messages. - - //Receive 1 - Message message2 = messageConsumer.receive(); - TextMessage txtMsg2 = (TextMessage) message2; - - //Receive 2 - Message message3 = messageConsumer.receive(); - TextMessage txtMsg3 = (TextMessage) message3; - - //Commit the transaction. This will consume the two messages. - session.commit(); - - //Receive should fail now as there should be no messages available. - Message message4 = messageConsumer.receive(); - //message4 will be null here. -``` - -### AUTO_ACKNOWLEDGE mode - -If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.AUTO_ACKNOWLEDGE`, the messages are automatically acknowledged. - -### DUPS_OK_ACKNOWLEDGE mode - -This mode instructs the session to lazily acknowledge the message, and it is okay if some messages are redelivered. However, in EDB JMS, this option is implemented the same way as `Session.AUTO_ACKNOWLEDGE`, where messages will be acknowledged automatically. - -### CLIENT_ACKNOWLEDGE mode - -If the first argument to `createSession()` or `createQueueSession()` is false and the second argument is `Session.CLIENT_ACKNOWLEDGE`, the messages are acknowledged when the client acknowledges the message by calling the `acknowledge()` method on a message. Acknowledging happens at the session level, and acknowledging one message will cause all the received messages to be acknowledged. - -For example, if we send 5 messages and then receive the 5 messages, acknowledging the 5th message will cause all 5 messages to be acknowledged. - -```java - MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); - - //Send 5 messages - for(int i=1; i<=5; i++) { - TextMessage msg = session.createTextMessage(); - String messageText = "Hello " + i; - msg.setText(messageText); - messageProducer.send(msg); - } - - MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); - - //Receive 4 - for(int i=1; i<=4; i++) { - Message message = messageConsumer.receive(); - TextMessage txtMsg = (TextMessage) message; - } - - //Receive the 5th message - Message message5 = messageConsumer.receive(); - TextMessage txtMsg5 = (TextMessage) message5; - - //Now acknowledge it and all the messages will be acknowledged. - txtMsg5.acknowledge(); - - //Try to receive again. This should return null as there is no message available. - Message messageAgain = messageConsumer.receive(); -``` - -## Message types - -EDB-JDBC JMS API supports the following message types and can be used in a standard way: - -| Message type | JMS type | -|------------------------|-------------------------| -| aq$_jms_message | javax.jms.Message | -| aq$_jms_text_message | javax.jms.TextMessage | -| aq$_jms_bytes_message | javax.jms.BytesMessage | -| aq$_jms_object_message | javax.jms.ObjectMessage | - -Please note that the corresponding payload types (user-defined types) are not pre-defined and must be created by the user before configuring the queue table. This is discussed in the upcoming sections. - -You can specify schema-qualified user-defined types, but the property types and message types must be in the same schema. - -## Message properties - -All of the above-mentioned message types supports setting and getting message properties. Before creating the actual message type, you must create the corresponding user-defined type for message properties. - -This example shows how to create the user-defined type for message properties: - -```sql -CREATE OR REPLACE TYPE AQ$_JMS_USERPROPERTY -AS object -( - NAME VARCHAR2(100), - VALUE VARCHAR2(2000) -); -``` - -All primitive types of message properties are supported. - -### TextMessage - -Text messages can be sent using the `TextMessage` interface. `EDBTextMessageImpl` is an implementation of `TextMessage`, but for most cases, you will be using the standard `TextMessage`. Before using the text message, it is necessary to create a user-defined type for it. - -This example shows how to create the user-defined messagetype for TextMessage: - -```sql -CREATE OR REPLACE TYPE AQ$_JMS_TEXT_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[], STRING_VALUE VARCHAR2(4000)); -``` - -Once the user-defined type is created, you can create the queue table using this type. This example shows how to create the queue table using the above created user-defined message type. - -```sql -EXEC DBMS_AQADM.CREATE_QUEUE_TABLE (queue_table => 'MSG_QUEUE_TABLE', queue_payload_type => 'AQ$_JMS_TEXT_MESSAGE', comment => 'Message queue table'); -``` - -After setting up the queue table, you can send and receive `TextMessages` using the standard procedure outlined in the Java code snippet: - -```java -MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); -// Create text message -TextMessage msg = session.createTextMessage(); -String messageText = "Hello there!"; -msg.setText(messageText); -msg.setStringProperty("myprop1", "test value 1"); -// Send message -messageProducer.send(msg); - -MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); -// Receive Message -Message message = messageConsumer.receive(); -TextMessage txtMsg = (TextMessage) message; -System.out.println(txtMsg.getText()); -System.out.println(txtMsg.getStringProperty("myprop1")); -``` - -### BytesMessage - -The `BytesMessage` is used to send a stream of bytes. `EDBBytesMessageImpl` is an implementation of `BytesMessage`, but in most cases, you will use the standard `BytesMessage`. Before using the bytes message, a user-defined type must be created. - -This example shows how to create the user-defined type for `BytesMessage`: - -```sql -CREATE OR REPLACE TYPE AQ$_JMS_BYTES_MESSAGE AS OBJECT (PROPERTIES AQ$_JMS_USERPROPERTY[], RAW_VALUE CLOB); -``` - -Now, `BytesMessage` can be sent and received in the standard way. - -This example shows how to create and use a `BytesMessage` in Java: - -```java -MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); -BytesMessage msg = session.createBytesMessage(); -String messageText = "Hello there!"; -msg.writeBytes(messageText.getBytes()); -messageProducer.send(msg); - -MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); -Message message = messageConsumer.receive(); -BytesMessage byteMsg = (BytesMessage) message; -byteMsg.reset(); -byte[] bytes = new byte[(int) byteMsg.getBodyLength()]; -byteMsg.readBytes(bytes); -System.out.println(new String(bytes)); -``` - -### ObjectMessage - -An `ObjectMessage` is used to send a serializable object as a message. `EDBObjectMessageImpl` is an implementation of `ObjectMessage`, but the standard `ObjectMessage` is most commonly used. - -Before using the `ObjectMessage`, it is necessary to create the user-defined type for the object message. - -This example shows how to create the user-defined type for `ObjectMessage`: - -```sql -CREATE OR REPLACE TYPE AQ$_JMS_OBJECT_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[], OBJECT_VALUE CLOB); -``` - -For example we have the following serializable Java class: - -```java -import java.io.Serializable; - -public class Emp implements Serializable { - private int id; - private String name; - private String role; - - // Getter and setter methods - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getRole() { - return role; - } - - public void setRole(String role) { - this.role = role; - } -} -``` - -This example shows how to use `ObjectMessage` to send a message containing an object of this class: - -```java -MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); - -// Create object message -ObjectMessage msg = session.createObjectMessage(); -Emp emp = new Emp(); -emp.setId(1); -emp.setName("Joe"); -emp.setRole("Manager"); -msg.setObject(emp); - -// Send message -messageProducer.send(msg); - -MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); - -// Receive Message -Message message = messageConsumer.receive(); -ObjectMessage objMsg = (ObjectMessage) message; -Emp empBack = (Emp) objMsg.getObject(); -System.out.println("ID: " + empBack.getId()); -System.out.println("Name: " + empBack.getName()); -System.out.println("Role: " + empBack.getRole()); -``` - -## Message - -A `Message` can be used to send a message with only properties and no body. `EDBMessageImpl` is an implementation of a `Message`, but you will most often use the standard Message. Before using a `Message`, it is required to create a user-defined type. - -This example shows how to create the user-defined type for `Message`: - -```sql -CREATE OR REPLACE TYPE AQ$_JMS_MESSAGE AS object(PROPERTIES AQ$_JMS_USERPROPERTY[]); -``` - -This example shows how to send a message that contains only properties and no body: - -```java -MessageProducer messageProducer = (MessageProducer) session.createProducer(queue); -// Create message. -Message msg = session.createMessage(); -msg.setStringProperty("myprop1", "test value 1"); -msg.setStringProperty("myprop2", "test value 2"); -msg.setStringProperty("myprop3", "test value 3"); -// Send message -messageProducer.send(msg); -MessageConsumer messageConsumer = (MessageConsumer) session.createConsumer(queue); -// Receive Message -message = messageConsumer.receive(); -System.out.println("myprop1: " + message.getStringProperty("myprop1")); -System.out.println("myprop2: " + message.getStringProperty("myprop2")); -System.out.println("myprop3: " + message.getStringProperty("myprop3")); -``` - -### Non-standard message - -EDB-JDBC JMS allows users to send and receive non-standard messages that are fully controlled by the API user. These messages do not support the setting and getting of properties. The process involves creating a user-defined type and setting it as the payload for the queue table. - -This example shows how to create a Java Bean corresponding to the type you created: - -```java -package mypackage; -import com.edb.jms.common.CompareValue; -import java.util.ArrayList; -public class MyType extends com.edb.aq.UDTType { - private Integer code; - private String project; - private String manager; - public MyType() { - } - /** - * @param code the code to set - */ - @CompareValue(0) - public void setCode(Integer code) { - this.code = code; - } - /** - * @return the code - */ - public Integer getCode() { - return code; - } - /** - * @param project the project to set - */ - @CompareValue(1) - public void setProject(String project) { - this.project = project; - } - /** - * @return the project - */ - public String getProject() { - return project; - } - @CompareValue(2) - public void setManager(String manager) { - this.manager = manager; - } - public String getManager() { - return manager; - } - public String valueOf() { - StringBuilder sql = new StringBuilder("CREATE TYPE "); - sql.append(getName() + " "); - sql.append("AS ("); - sql.append("code int, "); - sql.append("project TEXT);"); - return sql.toString(); - } - /** - * Override this method and call getter methods in the same order as in CREATE TYPE statement. - * CREATE OR REPLACE TYPE mytype AS object (code int, project text, manager varchar(10)) - * @return object array containing parameters. - */ - @Override - public Object[] getParamValues() { - ArrayList params = new ArrayList<>(); - params.add(getCode()); - params.add(getProject()); - params.add(getManager()); - return params.toArray(); - } -} -``` - -!!!note -- To create a user-defined class, it must extend the `com.edb.aq.operations.UDTType` class and override the `getParamValues()` method. In this method, you should add the attribute values to an `ArrayList` in the same order as they appear in the CREATE TYPE SQL statement in the database. -- Additionally, make sure to use the annotation @CompareValue(0) with better methods, as this specifies the order of methods when using the reflection API to reconstruct the object after dequeuing the message from the queue. - -Failure to meet these requirements may result in errors. -!!! - -This example shows how to send an object of this class as a message: - -```java -messageProducer = (EDBJmsMessageProducer) session.createProducer(queue); - MyType udtType1 = new MyType(); - udtType1.setProject("Test Project"); - udtType1.setManager("Joe"); - udtType1.setCode(321); - udtType1.setName("mytype"); //type name used in "CREATE TYPE" - messageProducer.send(udtType1); -``` - -This example shows how to receive this object as a message: - -```java -messageConsumer = (EDBJmsMessageConsumer) session.createConsumer(queue); - -Message message = messageConsumer.receive(); - -MyType myt = (MyType) message; -System.out.println("Code: "+ myt.getCode()); -System.out.println("Project: "+ myt.getProject()); -System.out.println("Manager: "+ myt.getManager()); -``` -## Nested types - -This example shows how to use nested types in the user-defined types: - -```sql -CREATE OR REPLACE TYPE innermostcustom AS object (testing_field_1 text); - -CREATE OR REPLACE TYPE innercustom AS object (testing_field_1 text, innermost innermostcustom); - -CREATE OR REPLACE TYPE custom_type AS object (testing_field text, inner innercustom); -``` - -In this example, `custom_type` is using `innercustom` as another user-defined type that in turn is using `innermostcustom` user-defined type. EDB Postgres Advanced Server supports the nested types in such fashion, however it may have performance implications at certain level. EDB JMS API also provides flexibility to read such nested types at the cost of an added performance impact. - -To illustrate this using the EDB JMS API, you must first create the equivalent objects that represent nested custom types as shown below: - -### InnermostCustom.java: - -```java -package mypackage; - -import com.edb.aq.UDTType; -import com.edb.jms.common.CompareValue; - -import java.util.ArrayList; - -public class InnermostCustom extends UDTType { - - public InnermostCustom() { - } - - private String testing_field_1; - - public String getTesting_field_1() { - return testing_field_1; - } - - @CompareValue(0) - public void setTesting_field_1(String testing_field_1) { - this.testing_field_1 = testing_field_1; - } - @Override - public Object[] getParamValues(){ - ArrayList params = new ArrayList(); - params.add(getTesting_field_1()); - return params.toArray(); - } -} -``` - -### InnerCustom.java - -```java -package mypackage; - -import com.edb.aq.UDTType; -import com.edb.jms.common.CompareValue; - -import java.util.ArrayList; - -public class InnerCustom extends UDTType { - - public InnerCustom() { - } - - private String testing_field_1; - private InnermostCustom innermostCustom; - - public String getTesting_field_1() { - return testing_field_1; - } - - @CompareValue(0) - public void setTesting_field_1(String testing_field_1) { - this.testing_field_1 = testing_field_1; - } - - public InnermostCustom getInnermostCustom() { - return innermostCustom; - } - - @CompareValue(1) - public void setInnermostCustom(InnermostCustom innermostCustom) { - this.innermostCustom = innermostCustom; - } - @Override - public Object[] getParamValues(){ - ArrayList params = new ArrayList(); - params.add(getTesting_field_1()); - params.add(getInnermostCustom()); - return params.toArray(); - } -} -``` - -### CustomType.java - -```java -package mypackage; - -import com.edb.aq.UDTType; -import com.edb.jms.common.CompareValue; - -import java.util.ArrayList; - -public class CustomType extends UDTType { - - private String testing_field; - private InnerCustom innerCustom; - - public String getTesting_field() { - return testing_field; - } - - @CompareValue(0) - public void setTesting_field(String testing_field) { - this.testing_field = testing_field; - } - - public InnerCustom getInnerCustom() { - return innerCustom; - } - - @CompareValue(1) - public void setInnerCustom(InnerCustom innerCustom) { - this.innerCustom = innerCustom; - } - - public CustomType() { - - } - - public Object[] getParamValues(){ - ArrayList params = new ArrayList(); - params.add(getTesting_field()); - params.add(getInnerCustom()); - return params.toArray(); - } -} -``` - -This example shows how to read such nested types: - -```java - EDBJmsMessageProducer messageProducer = (EDBJmsMessageProducer) session.createProducer(queue_1); - - InnermostCustom innermostCustom = new InnermostCustom(); - innermostCustom.setTesting_field_1("Innermost set"); - innermostCustom.setName("innermostCustom"); - - InnerCustom innerCustom = new InnerCustom(); - innerCustom.setTesting_field_1("Inner set"); - innerCustom.setInnermostCustom(innermostCustom); - innerCustom.setName("innercustom"); - - CustomType customType = new CustomType(); - customType.setTesting_field("EDB"); - customType.setInnerCustom(innerCustom); - customType.setName("custom_type"); - - messageProducer.send(customType); - - EDBJmsMessageConsumer messageConsumer = (EDBJmsMessageConsumer) session.createConsumer(queue_1); - - Message message = messageConsumer.receive(); - - CustomType myType = (CustomType) message; - InnerCustom innerCustom_1 = myType.getInnerCustom(); - InnermostCustom innermostCustom1 = innerCustom_1.getInnermostCustom(); - - System.out.println("Outer type test field: " + myType.getTesting_field()); - System.out.println("Inner type test field: " + innerCustom_1.getTesting_field_1()); - System.out.println("Most Inner type test field: " + innermostCustom1.getTesting_field_1()); -``` From 02e9ec2f0ef740d6a456b3375dd7712e12459e88 Mon Sep 17 00:00:00 2001 From: Betsy Gitelman Date: Thu, 19 Sep 2024 16:15:29 -0400 Subject: [PATCH 07/26] Edits to PEM with PgBouncer-customer issue PR5950 --- .../pem_pgbouncer/configuring_pgBouncer.mdx | 12 +++++------- .../pem_pgbouncer/configuring_the_pem_agent.mdx | 6 +++--- .../pem/9/considerations/pem_pgbouncer/index.mdx | 2 +- ...pem_agent_connection_management_mechanism.mdx | 4 ++-- .../preparing_the_pem_database_server.mdx | 16 ++++++++-------- 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_pgBouncer.mdx b/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_pgBouncer.mdx index fca3b2256ca..449f0b092a1 100644 --- a/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_pgBouncer.mdx +++ b/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_pgBouncer.mdx @@ -13,15 +13,13 @@ You must configure PgBouncer to work with the PEM database server. ## Prerequisites -- If you are running EDB Postgres Advanced Server, you have installed [EDB PgBouncer](/pgbouncer/latest/installing). +- If you're running EDB Postgres Advanced Server, install [EDB PgBouncer](/pgbouncer/latest/installing). - Or - -- If you are running EDB Postgres Extended Server or PostgreSQL, you have installed community [PgBouncer](https://www.pgbouncer.org/install.html). +- If you're running EDB Postgres Extended Server or PostgreSQL, install community [PgBouncer](https://www.pgbouncer.org/install.html). ### EDB PgBouncer and PgBouncer installation considerations -The name and location of the directories and files in the configuration steps, as well as the user, depend on whether you installed the community version of PgBouncer or EDB PgBouncer. If you have installed community PgBouncer (whether you install it from the community repo or the EDB repo), replace the names of the files and directories in the worked example with the values for PgBouncer. +The name and location of the directories and files in the configuration steps, as well as the user, depend on whether you installed the community version of PgBouncer or EDB PgBouncer. If you installed community PgBouncer (whether you install it from the community repo or the EDB repo), replace the names of the files and directories in the worked example with the values for PgBouncer. | Name | PgBouncer | EDB PgBouncer | |---------------------|---------------------------|------------------------------------| @@ -33,9 +31,9 @@ The name and location of the directories and files in the configuration steps, a ## Configuring PgBouncer -This example configures EDB PgBouncer with the `enterprisedb` system user. +This example configures EDB PgBouncer with the enterprisedb system user. -If you are running community PgBouncer, replace the names of the directories, files and user as explained in [Location of PgBouncer directories](#edb-pgbouncer-and-pgbouncer-installation-considerations) . +If you're running community PgBouncer, replace the names of the directories, files, and user as explained in [Location of PgBouncer directories](#edb-pgbouncer-and-pgbouncer-installation-considerations). 1. Open a terminal window and navigate to the PgBouncer directory. diff --git a/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_the_pem_agent.mdx b/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_the_pem_agent.mdx index 9f234f89268..1a44cb2650c 100644 --- a/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_the_pem_agent.mdx +++ b/product_docs/docs/pem/9/considerations/pem_pgbouncer/configuring_the_pem_agent.mdx @@ -10,17 +10,17 @@ redirects: ## Prerequisites -You have [installed the PEM agent](../../installing_pem_agent/). +[Install the PEM agent](../../installing_pem_agent/). !!!note - Do not configure PEM agents with `enable_smtp`, `enable_snmp`, or `enable_webhook` set to `true` in the `agent.cfg` file to connect through PgBouncer. SNMP, SMTP, and Webhook spoolers use the LISTEN/NOTIFY mechanism provided by Postgres to send notifications asynchronously. Since PgBouncer doesn’t support the LISTEN/NOTIFY mechanism in transaction mode, connecting the agent to PgBouncer can cause notifications to be delayed or not delivered at all. Instead, connect the PEM agent directly to the PEM backend database. + Don't configure PEM agents with `enable_smtp`, `enable_snmp`, or `enable_webhook` set to `true` in the `agent.cfg` file to connect through PgBouncer. SNMP, SMTP, and Webhook spoolers use the LISTEN/NOTIFY mechanism provided by Postgres to send notifications asynchronously. Since PgBouncer doesn’t support the LISTEN/NOTIFY mechanism in transaction mode, connecting the agent to PgBouncer can cause notifications to be delayed or not delivered at all. Instead, connect the PEM agent directly to the PEM backend database. !!! Now you can choose to [configure a new PEM agent](#configuring-a-new-pem-agent) or [use an existing PEM agent](#configuring-an-existing-pem-agent) for PgBouncer. ## Configuring a new PEM agent -After installing the PEM agent, configure it to work with a particular PEM database server. Use the following command: +After installing the PEM agent, configure it to work with a particular PEM database server: ```shell PGSSLMODE=require PEM_SERVER_PASSWORD=pem_admin1_password \ diff --git a/product_docs/docs/pem/9/considerations/pem_pgbouncer/index.mdx b/product_docs/docs/pem/9/considerations/pem_pgbouncer/index.mdx index ecdd5a57885..1208d029130 100644 --- a/product_docs/docs/pem/9/considerations/pem_pgbouncer/index.mdx +++ b/product_docs/docs/pem/9/considerations/pem_pgbouncer/index.mdx @@ -20,7 +20,7 @@ navigation: You can use PgBouncer as a connection pooler for limiting the number of connections from the PEM agent to the Postgres Enterprise Manager (PEM) server on non-Windows machines: - [PEM server and agent connection management mechanism](pem_server_pem_agent_connection_management_mechanism) provides an introduction of the PgBouncer-PEM infrastructure. -- [Preparing the PEM Database Server](preparing_the_pem_database_server) provides information about preparing the PEM database server to be used with PgBouncer. +- [Preparing the PEM database server](preparing_the_pem_database_server) provides information about preparing the PEM database server to be used with PgBouncer. - [Configuring PgBouncer](configuring_pgBouncer) provides detailed information about configuring PgBouncer to allow it to work with the PEM database server. - [Configuring the PEM agent](configuring_the_pem_agent) provides detailed information about configuring a PEM agent to connect to PgBouncer. diff --git a/product_docs/docs/pem/9/considerations/pem_pgbouncer/pem_server_pem_agent_connection_management_mechanism.mdx b/product_docs/docs/pem/9/considerations/pem_pgbouncer/pem_server_pem_agent_connection_management_mechanism.mdx index 80fe1f6630b..b6bb6071b7c 100644 --- a/product_docs/docs/pem/9/considerations/pem_pgbouncer/pem_server_pem_agent_connection_management_mechanism.mdx +++ b/product_docs/docs/pem/9/considerations/pem_pgbouncer/pem_server_pem_agent_connection_management_mechanism.mdx @@ -18,9 +18,9 @@ For example, a user agent with ID 1 connects to the PEM database server as agent ## With PgBouncer -In a PgBouncer-enabled environment, PEM agents cannot connect to the PEM database server directly. PEM agents must use a proxy user that you configure specifically for the connection to PgBouncer. In the example, the proxy user handling all PEM agent connections is called `pem_agent_user1`. +In a PgBouncer-enabled environment, PEM agents can't connect to the PEM database server directly. PEM agents must use a proxy user that you configure specifically for the connection to PgBouncer. In the example, the proxy user handling all PEM agent connections is called `pem_agent_user1`. -Once the PEM agents connect to PgBouncer using SSL, PgBouncer is responsible for managing connection requests to the PEM database server. PgBouncer uses the rules you have configured for connection pooling to manage the incoming connection requests, for example, by respecting the established maximum number of active connections. +Once the PEM agents connect to PgBouncer using SSL, PgBouncer is responsible for managing connection requests to the PEM database server. PgBouncer uses the rules you configured for connection pooling to manage the incoming connection requests, for example, by respecting the established maximum number of active connections. ![Connecting to pgBouncer.](../../images/pem_with_pgbouncer.png) diff --git a/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx b/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx index 0ddeb82c21c..58fdb878fbd 100644 --- a/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx +++ b/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx @@ -8,15 +8,15 @@ redirects: - /pem/latest/pem_online_help/09_toc_pem_configure_pgbouncer/02_pem_pgbouncer_preparing_dbserver/ --- -You must configure dedicated users and create an SSL key and certificate on the PEM database server to enable connection pooling for PEM with PgBouncer. +To enable connection pooling for PEM with PgBouncer, you must configure dedicated users and create an SSL key and certificate on the PEM database server. -This example shows how to prepare the PEM database server with the `enterprisedb` user on a RHEL-based operating system with EDB Postgres Advanced Server version 16. The location of your data, the configuration and key files, and the user you employ to perform the configuration may differ depending on your OS and Postgres distribution. +This example shows how to prepare the PEM database server with the enterprisedb user on a RHEL-based operating system with EDB Postgres Advanced Server version 16. The location of your data, the configuration and key files, and the user you use to perform the configuration may differ depending on your OS and Postgres distribution. ## Prerequisites -- You are connected to the `pem` database of the PEM database server. +- You're connected to the `pem` database of the PEM database server. -- You are connected as `enterprisedb` or `postgres` user. The user depends on your Postgres distribution. +- You're connected as the enterprisedb or postgres user. The user depends on your Postgres distribution. | Postgres distribution | User | |------------------------------|--------------| @@ -40,7 +40,7 @@ This example shows how to prepare the PEM database server with the `enterprisedb GRANT ROLE ``` -1. Create a user named pem_admin1 (not a superuser) with `pem_admin` and `pem_agent_pool` role membership. This user is used to register the agent to the PEM server and manage access to the PEM database. +1. Create a user named pem_admin1 (not a superuser) with pem_admin and pem_agent_pool role membership. This user registers the agent to the PEM server and manages access to the PEM database. ```sql CREATE ROLE pem_admin1 PASSWORD 'ANY_PASSWORD' LOGIN CREATEROLE; @@ -117,7 +117,7 @@ This example shows how to prepare the PEM database server with the `enterprisedb pem_agent_pool pem_agent_pool pgbouncer ``` -1. Restart the Postgres service. Replace the `` placeholder with the name of the Postgres instance systemd service name: +1. Restart the Postgres service. Replace `` with the name of the Postgres instance systemd service name: ```shell systemctl restart @@ -125,7 +125,7 @@ This example shows how to prepare the PEM database server with the `enterprisedb ## Creating the SSL key and certificate for PgBouncer-PEM authentication -Create a key and certificate for the `pem_agent_pool` group role. Then, move the files to the PgBouncer instance to allow authentication between the PEM database server and PgBouncer. +Create a key and certificate for the pem_agent_pool group role. Then, move the files to the PgBouncer instance to allow authentication between the PEM database server and PgBouncer. This example runs EDB Postgres Advanced Server on RHEL. When setting your environment variables, choose the correct directories according to your operating system and Postgres distribution. @@ -175,7 +175,7 @@ This example runs EDB Postgres Advanced Server on RHEL. When setting your enviro openssl genrsa -out pem_agent_pool.key 4096 ``` -1. Create a certificate-signing request (CSR). Replace the `-subj` attributes in `<...>` as required. Ensure the Common Name (CN) is set to the `pem_agent_pool` group role name: +1. Create a certificate-signing request (CSR). Replace the `-subj` attributes in `<...>` as required. Ensure the common name (CN) is set to the pem_agent_pool group role name: ```shell openssl req -new -key pem_agent_pool.key -out pem_agent_pool.csr -subj '/C=/ST=/L=/O=/CN=pem_agent_pool' From cf9fe7a1714aa284b3628662533d86c0dcfe3e8e Mon Sep 17 00:00:00 2001 From: Betsy Gitelman Date: Thu, 19 Sep 2024 16:21:07 -0400 Subject: [PATCH 08/26] Apply suggestions from code review --- .../pem_pgbouncer/preparing_the_pem_database_server.mdx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx b/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx index 58fdb878fbd..d5ccc809c33 100644 --- a/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx +++ b/product_docs/docs/pem/9/considerations/pem_pgbouncer/preparing_the_pem_database_server.mdx @@ -14,9 +14,9 @@ This example shows how to prepare the PEM database server with the enterprisedb ## Prerequisites -- You're connected to the `pem` database of the PEM database server. +- Connect to the `pem` database of the PEM database server. -- You're connected as the enterprisedb or postgres user. The user depends on your Postgres distribution. +- Connect as the enterprisedb or postgres user based on your Postgres distribution. | Postgres distribution | User | |------------------------------|--------------| From bc41d81fa03c4edde9998d06df51b90ad87a701d Mon Sep 17 00:00:00 2001 From: sszhao1020 <89435179+sszhao1020@users.noreply.github.com> Date: Fri, 20 Sep 2024 13:47:49 +0800 Subject: [PATCH 09/26] Update indentation for the example yaml file The previous example doesn't work due to the improper indentation. --- .../console/estate/agent/install-agent.mdx | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx b/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx index d21aefce3e7..104d6fd401e 100644 --- a/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx +++ b/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx @@ -130,26 +130,27 @@ Here is an example `beacon_agent.yaml` file configured for a database named `sal ```yaml agent: -access_key: $BEACON_AGENT_ACCESS_KEY -access_key_grpc_header: "x-access-key" -batch_size: 100 -beacon_server: "beacon.biganimal.com:443" -feature_flag_interval: 10m0s -project_id: "" -providers: -- "onprem" + access_key: "$BEACON_AGENT_ACCESS_KEY" + access_key_grpc_header: "x-access-key" + batch: + size: 100 + beacon_server: "beacon.biganimal.com:443" + feature_flag_interval: 10m0s + project_id: "" + providers: + - "onprem" provider: -onprem: -databases: - sales_reporting: - dsn: “$DSN” - tags: - - "sales" - - "reports" -host: - resource_id: "postgresql.lan" - tags: [] -poll_interval: 5m0s + onprem: + databases: + sales_reporting: + dsn: $DSN + tags: + - "sales" + - "reports" + host: + resource_id: "postgresql.lan" + tags: [] + poll_interval: 5m0s ``` ## Test Beacon Agent locally. From c5db0a0135c2b1b8abe74529bd882d0685080323 Mon Sep 17 00:00:00 2001 From: sszhao1020 <89435179+sszhao1020@users.noreply.github.com> Date: Fri, 20 Sep 2024 13:54:38 +0800 Subject: [PATCH 10/26] Update install-agent.mdx --- .../edb-postgres-ai/console/estate/agent/install-agent.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx b/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx index 104d6fd401e..fa6d7c26ca0 100644 --- a/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx +++ b/advocacy_docs/edb-postgres-ai/console/estate/agent/install-agent.mdx @@ -143,7 +143,7 @@ provider: onprem: databases: sales_reporting: - dsn: $DSN + dsn: "$DSN" tags: - "sales" - "reports" From 6b8401ed0fda00ded8ed6d2e783d3f3896710699 Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan Date: Fri, 20 Sep 2024 11:47:34 +0100 Subject: [PATCH 11/26] Added reference, converted to tables, added defaults Signed-off-by: Dj Walker-Morgan --- product_docs/docs/pgd/5/reference/index.json | 1 + product_docs/docs/pgd/5/reference/index.mdx | 1 + .../docs/pgd/5/reference/pgd-settings.mdx | 41 ++++++++++++------- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/product_docs/docs/pgd/5/reference/index.json b/product_docs/docs/pgd/5/reference/index.json index 39afee609a0..18dbfdf92ee 100644 --- a/product_docs/docs/pgd/5/reference/index.json +++ b/product_docs/docs/pgd/5/reference/index.json @@ -117,6 +117,7 @@ "bdrglobal_lock_timeout": "/pgd/latest/reference/pgd-settings#bdrglobal_lock_timeout", "bdrglobal_lock_statement_timeout": "/pgd/latest/reference/pgd-settings#bdrglobal_lock_statement_timeout", "bdrglobal_lock_idle_timeout": "/pgd/latest/reference/pgd-settings#bdrglobal_lock_idle_timeout", + "bdrlock_table_locking": "/pgd/latest/reference/pgd-settings#bdrlock_table_locking", "bdrpredictive_checks": "/pgd/latest/reference/pgd-settings#bdrpredictive_checks", "bdrreplay_progress_frequency": "/pgd/latest/reference/pgd-settings#bdrreplay_progress_frequency", "bdrstandby_slot_names": "/pgd/latest/reference/pgd-settings#bdrstandby_slot_names", diff --git a/product_docs/docs/pgd/5/reference/index.mdx b/product_docs/docs/pgd/5/reference/index.mdx index 2b57f037fb7..437d97755cc 100644 --- a/product_docs/docs/pgd/5/reference/index.mdx +++ b/product_docs/docs/pgd/5/reference/index.mdx @@ -172,6 +172,7 @@ The reference section is a definitive listing of all functions, views, and comma * [`bdr.global_lock_timeout`](pgd-settings#bdrglobal_lock_timeout) * [`bdr.global_lock_statement_timeout`](pgd-settings#bdrglobal_lock_statement_timeout) * [`bdr.global_lock_idle_timeout`](pgd-settings#bdrglobal_lock_idle_timeout) + * [`bdr.lock_table_locking`](pgd-settings#bdrlock_table_locking) * [`bdr.predictive_checks`](pgd-settings#bdrpredictive_checks) ### [Node management](pgd-settings#node-management) * [`bdr.replay_progress_frequency`](pgd-settings#bdrreplay_progress_frequency) diff --git a/product_docs/docs/pgd/5/reference/pgd-settings.mdx b/product_docs/docs/pgd/5/reference/pgd-settings.mdx index ac7d3d6a45e..e4614fd4a97 100644 --- a/product_docs/docs/pgd/5/reference/pgd-settings.mdx +++ b/product_docs/docs/pgd/5/reference/pgd-settings.mdx @@ -37,13 +37,12 @@ identify rows that are updated or deleted. The accepted values are: -- `default` — Records the old values of the columns of the primary key, - if any (this is the default PostgreSQL behavior). -- `full` — Records the old values of all columns in the row. -- `nothing` — Records no information about the old row. -- `auto` — Tables with PK are created with REPLICA IDENTITY DEFAULT, - and tables without PK are created with REPLICA IDENTITY FULL. This is - the default PGD behavior. +| Value | Description | +|---|---| +| `default` | Records the old values of the columns of the primary key, if any (this is the default PostgreSQL behavior). | +| `full` | Records the old values of all columns in the row. | +| `nothing` | Records no information about the old row. | +| `auto` | Tables with PK are created with REPLICA IDENTITY DEFAULT, and tables without PK are created with REPLICA IDENTITY FULL. This is the default PGD behavior. | See the [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html#SQL-CREATETABLE-REPLICA-IDENTITY) for more details. @@ -105,10 +104,13 @@ This parameter can be set only by bdr_superuser or superuser roles. Possible options are: -- `all` — Use global locking for all DDL operations. -- `dml` — Use global locking only for DDL operations that need to prevent - writes by taking the global DML lock for a relation. -- `off` — Don't use global locking for DDL operations. +| Value | Description | +| --- | --- | +| `all` | Use global locking for all DDL operations. (Default) | +| `dml` | Use global locking only for DDL operations that need to prevent writes by taking the global DML lock for a relation. | +| `off` | Don't use global locking for DDL operations. | + +Default is `all`. A `LOG`-level log message is emitted to the PostgreSQL server logs whenever `bdr.ddl_replication` is set to `off`. Additionally, a `WARNING` message is @@ -152,6 +154,15 @@ Sets the maximum allowed duration of any statement holding a global lock Sets the maximum allowed duration of idle time in a transaction holding a global lock (default is 10 minutes). A value of zero disables this timeout. +### `bdr.lock_table_locking` + +Defaults to `off`. When enabled PGD treats every lock as a global DML lock. This makes the entire cluster wait for the lock to be released. This setting is useful for debugging and testing purposes. + +| Value | Description | +| --- | --- | +| `on` | Use global locking for all table locks. | +| `off` | Don't use global locking for table locks. (Default) | + ### `bdr.predictive_checks` Sets the log level for predictive checks (currently used only by global locks). @@ -252,10 +263,10 @@ Specifies the action to take if a clock skew higher than There are two possible values for this setting: -- `WARN` — Log a warning about this fact. The warnings are logged once - per minute (the default) at the maximum to prevent flooding the server log. -- `WAIT` — Wait until the current local timestamp is no longer older - than remote commit timestamp minus the `bdr.maximum_clock_skew`. +| Value | Description | +| --- | --- | +| `WARN` | Log a warning about this fact. The warnings are logged once per minute at the maximum to prevent flooding the server log. | +| `WAIT` | Wait until the current local timestamp is no longer older than remote commit timestamp minus the `bdr.maximum_clock_skew`. | ### `bdr.accept_connections` From 95171d32dfe5db3aaec6f21770984cf0ff19688f Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:10:30 +0100 Subject: [PATCH 12/26] Update product_docs/docs/pgd/5/reference/pgd-settings.mdx Co-authored-by: Florin Irion --- product_docs/docs/pgd/5/reference/pgd-settings.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product_docs/docs/pgd/5/reference/pgd-settings.mdx b/product_docs/docs/pgd/5/reference/pgd-settings.mdx index e4614fd4a97..08633f62198 100644 --- a/product_docs/docs/pgd/5/reference/pgd-settings.mdx +++ b/product_docs/docs/pgd/5/reference/pgd-settings.mdx @@ -156,7 +156,7 @@ lock (default is 10 minutes). A value of zero disables this timeout. ### `bdr.lock_table_locking` -Defaults to `off`. When enabled PGD treats every lock as a global DML lock. This makes the entire cluster wait for the lock to be released. This setting is useful for debugging and testing purposes. +Defaults to off. This configuration option sets locking behavior for LOCK TABLE Statement; when enabled, LOCK TABLE statement will also take a global DML lock on the cluster, blocking other locking statements. | Value | Description | | --- | --- | From 5293e5cd5ab377dee0ed4eb3048a6efd069ceb28 Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan Date: Thu, 12 Sep 2024 17:14:57 +0100 Subject: [PATCH 13/26] Rework bdr.drop_node Signed-off-by: Dj Walker-Morgan --- .../pgd/5/reference/functions-internal.mdx | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/product_docs/docs/pgd/5/reference/functions-internal.mdx b/product_docs/docs/pgd/5/reference/functions-internal.mdx index 78d6388ef4c..dfad8066c9f 100644 --- a/product_docs/docs/pgd/5/reference/functions-internal.mdx +++ b/product_docs/docs/pgd/5/reference/functions-internal.mdx @@ -156,19 +156,25 @@ bdr.difference_fix_xact_set_avoid_conflict() ### `bdr.drop_node` -Drops a node. - -!!! Warning - This function isn't intended for regular use. Execute it only - if instructed by Technical Support. +Drops a node's metadata. This function removes the metadata for a given node from the local database. The node can be either: -- The local node, in which case all the node metadata is removed, - including information about remote nodes. -- A remote node, in which case only metadata for that specific - node is removed. +- The local node, in which case it removes all the node metadata, including information about remote nodes. +- A remote node, in which case it only removes metadata for that specific node. + + + +!!! Important When to use `bdr.drop_node()` +You don't have to use `bdr.drop_node` to remove a node from a PGD group if you are reusing the node name. This is because PGD can reuse existing node names providing the node being named is in a `PARTED` state. + +Generally, you should use [`bdr.part_node`](/pgd/latest/reference/nodes-management-interfaces#bdrpart_node) to remove a node from a PGD group (which sets the node to `PARTED` state). You should only use `bdr.drop_node` function when: + +* if you need to remove metadata of a `PARTED` node under the instruction of EDB Technical Support +* where specifically instructed in the documentation to use it. + +!!! #### Synopsis From c927cb9fc302b111accfdfc68fbee2323ac982b2 Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:46:18 +0100 Subject: [PATCH 14/26] Update product_docs/docs/pgd/5/reference/functions-internal.mdx --- product_docs/docs/pgd/5/reference/functions-internal.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product_docs/docs/pgd/5/reference/functions-internal.mdx b/product_docs/docs/pgd/5/reference/functions-internal.mdx index dfad8066c9f..d7f349d3f44 100644 --- a/product_docs/docs/pgd/5/reference/functions-internal.mdx +++ b/product_docs/docs/pgd/5/reference/functions-internal.mdx @@ -171,7 +171,7 @@ You don't have to use `bdr.drop_node` to remove a node from a PGD group if you a Generally, you should use [`bdr.part_node`](/pgd/latest/reference/nodes-management-interfaces#bdrpart_node) to remove a node from a PGD group (which sets the node to `PARTED` state). You should only use `bdr.drop_node` function when: -* if you need to remove metadata of a `PARTED` node under the instruction of EDB Technical Support +* you need to remove metadata of a `PARTED` node under the instruction of EDB Technical Support * where specifically instructed in the documentation to use it. !!! From 21e4e52514db96841d3de1c574c9c78bffcf352f Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan Date: Mon, 23 Sep 2024 11:03:57 +0100 Subject: [PATCH 15/26] Simplifiication pass Signed-off-by: Dj Walker-Morgan --- .../docs/pgd/5/reference/functions-internal.mdx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/product_docs/docs/pgd/5/reference/functions-internal.mdx b/product_docs/docs/pgd/5/reference/functions-internal.mdx index d7f349d3f44..fc391a29503 100644 --- a/product_docs/docs/pgd/5/reference/functions-internal.mdx +++ b/product_docs/docs/pgd/5/reference/functions-internal.mdx @@ -167,12 +167,14 @@ database. The node can be either: !!! Important When to use `bdr.drop_node()` -You don't have to use `bdr.drop_node` to remove a node from a PGD group if you are reusing the node name. This is because PGD can reuse existing node names providing the node being named is in a `PARTED` state. +Because PGD can reuse existing node names providing the node name belongs to a node in a `PARTED` state, you should not use `bdr.drop_node` to remove the original node metadata. -Generally, you should use [`bdr.part_node`](/pgd/latest/reference/nodes-management-interfaces#bdrpart_node) to remove a node from a PGD group (which sets the node to `PARTED` state). You should only use `bdr.drop_node` function when: +Use of this internal function is limited to: -* you need to remove metadata of a `PARTED` node under the instruction of EDB Technical Support -* where specifically instructed in the documentation to use it. +* when you are instructed to by EDB Technical Support, or +* where you are specifically instructed in the documentation to use `bdr.drop_node`. + +You should use [`bdr.part_node`](/pgd/latest/reference/nodes-management-interfaces#bdrpart_node) to remove a node from a PGD group. That function sets the node to `PARTED` state and enable reuse of the node name. !!! From 6d6a424847c68d0dc3a739ba74947f7624f0ec9d Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> Date: Mon, 23 Sep 2024 11:41:18 +0100 Subject: [PATCH 16/26] Update product_docs/docs/pgd/5/reference/functions-internal.mdx --- product_docs/docs/pgd/5/reference/functions-internal.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/product_docs/docs/pgd/5/reference/functions-internal.mdx b/product_docs/docs/pgd/5/reference/functions-internal.mdx index fc391a29503..0c74b97e916 100644 --- a/product_docs/docs/pgd/5/reference/functions-internal.mdx +++ b/product_docs/docs/pgd/5/reference/functions-internal.mdx @@ -167,7 +167,7 @@ database. The node can be either: !!! Important When to use `bdr.drop_node()` -Because PGD can reuse existing node names providing the node name belongs to a node in a `PARTED` state, you should not use `bdr.drop_node` to remove the original node metadata. +Do not use `bdr.drop_node()` to drop node metadata and reuse node names. PGD can reuse existing node names providing the node name belongs to a node in a `PARTED` state. Use `bdr.part_node()` to remove the original node and place it in a `PARTED` state. Use of this internal function is limited to: From 3912a3177c555202bc4a27cc8aef4b1c30f3ec4d Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan Date: Mon, 23 Sep 2024 15:45:50 +0100 Subject: [PATCH 17/26] Trust Center in footer menu Signed-off-by: Dj Walker-Morgan --- src/components/footer.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/footer.js b/src/components/footer.js index 23e2f0368ea..0721ac71513 100644 --- a/src/components/footer.js +++ b/src/components/footer.js @@ -64,10 +64,14 @@ const Footer = ({ timestamp, githubFileLink }) => ( GDPR · + + Trust Center + + · Security - . + · Date: Mon, 23 Sep 2024 13:44:04 +0530 Subject: [PATCH 18/26] Cloud Service Edited the title and added new image as per suggestion provided by yogesh jain --- .../images/monitoring_and_logging_tab.png | 4 ++-- .../monitoring_using_biganimal_observability/index.mdx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png index 3ff6d1ff5b6..452e15c5751 100644 --- a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png +++ b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:88cd9f2cc522bf0cf6c358f0b1dfb46d765c14b6f8cca1c1fd4e53cab76db048 -size 1666158 +oid sha256:519880fd48d9e38ed00f56c6137ebbd06e465cdc4c7ddcfbc3061ea0fff8154d +size 594743 diff --git a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx index de29395a994..a7acf3d38ba 100644 --- a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx +++ b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx @@ -1,5 +1,5 @@ --- -title: "Monitoring using BigAnimal Observability" +title: "Monitoring using Cloud Service Observability" redirects: - /biganimal/latest/using_cluster/05_monitoring_and_logging/monitoring_using_pemx/ From 689a12dbb7397bb0ea5bd9c80efee8c704e34340 Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Mon, 23 Sep 2024 13:53:07 +0530 Subject: [PATCH 19/26] exchanged the image --- .../images/monitoring_and_logging.png | 3 +++ .../images/monitoring_and_logging_tab.png | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging.png delete mode 100644 advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png diff --git a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging.png b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging.png new file mode 100644 index 00000000000..8d671c71c98 --- /dev/null +++ b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d49b1b4537a04f3bbe327193e46b92bb697401f44382bbae493feb2e9cb06442 +size 1351516 diff --git a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png deleted file mode 100644 index 452e15c5751..00000000000 --- a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:519880fd48d9e38ed00f56c6137ebbd06e465cdc4c7ddcfbc3061ea0fff8154d -size 594743 From 59197f4ce546e351a02a38a657794a033709a227 Mon Sep 17 00:00:00 2001 From: nidhibhammar <59045594+nidhibhammar@users.noreply.github.com> Date: Mon, 23 Sep 2024 14:00:59 +0530 Subject: [PATCH 20/26] fixed the image name --- ...{monitoring_and_logging.png => monitoring_and_logging_tab.png} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/{monitoring_and_logging.png => monitoring_and_logging_tab.png} (100%) diff --git a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging.png b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png similarity index 100% rename from advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging.png rename to advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/images/monitoring_and_logging_tab.png From b054f07a92c1b43f51a9e7ce9afbf231817e66ee Mon Sep 17 00:00:00 2001 From: Josh Heyer Date: Tue, 24 Sep 2024 04:16:06 +0000 Subject: [PATCH 21/26] no-op change to trigger page rebuild --- .../monitoring_using_biganimal_observability/index.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx index a7acf3d38ba..305832fb6d4 100644 --- a/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx +++ b/advocacy_docs/edb-postgres-ai/cloud-service/using_cluster/monitoring_and_logging/monitoring_using_biganimal_observability/index.mdx @@ -10,6 +10,7 @@ Cloud Service Observability is an integrated monitoring and alerting solution in Cloud Service Observability renders insightful charts that empower you to actively monitor each metric's behavior. It provides a streamlined path for you to take prompt and informed actions based on the generated alerts. This cohesive monitoring and alert system ensures comprehensive oversight and prompt responses in the Cloud Service environment. When you log in, Cloud Service Observability monitoring widgets are displayed on the overview page on the project summary page. These widgets are available only for the deployed Postgres clusters and aren't available for the clusters in the provisioning process. They provide high-level, key information on: + - Memory - CPU - Storage usage percentages From 3acf2b935e91487222612ebfebcc1679c2d297a4 Mon Sep 17 00:00:00 2001 From: gvasquezvargas Date: Mon, 9 Sep 2024 15:06:50 +0200 Subject: [PATCH 22/26] suggestion for style guide, full stop in frontmatter descriptions --- .../community/contributing/styleguide.mdx | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/advocacy_docs/community/contributing/styleguide.mdx b/advocacy_docs/community/contributing/styleguide.mdx index c38351cc472..f76462cc9e9 100644 --- a/advocacy_docs/community/contributing/styleguide.mdx +++ b/advocacy_docs/community/contributing/styleguide.mdx @@ -74,6 +74,7 @@ Included in this guide: * 13 [Dates](#dates) * 14 [Terminology considerations](#terminology-considerations) * 15 [Trademark symbols](#trademark-symbols) +* 16 [Frontmatter](#frontmatter) ## Language and tone @@ -656,4 +657,20 @@ Examples: EDB Postgres® AI, EDB Postgres® Analytics, EDB Postgres® Machine Le For other trademarks, the documentation site already includes a general disclaimer at the footer of every page called "Trademark" which links to https://www.enterprisedb.com/trademarks. Contrary to the specifications on [Trademarks](https://www.enterprisedb.com/trademarks), don't include the symbol in page titles, -because the symbol can affect how search engines index and find pages. \ No newline at end of file +because the symbol can affect how search engines index and find pages. + +## Frontmatter + +The frontmatter is located at the top of every markdown page, and allows you to specify metadata and options in YAML language. Frontmatter lets you control how a page will render. + +Ensure your page, at minimum, includes a `title` and `description` as metadata. It can include other metadata such as `navTitle`, `deepToC`, etc. + +```yaml +--- +title: Working with the Repo +description: Step by step instructions to install and use the docs repo. +--- +``` + +!!!note + Ensure the `description` has a final stop, even if it isn't a full grammatical sentence. Descriptions are used to dynamically build a summary for each section in `index` pages. Since all descriptions are then displayed next to each other, add a full stop to ensure visual consistency. From 30d081f8f70c60b8481fb26e80b17840bfa67037 Mon Sep 17 00:00:00 2001 From: Florin Irion Date: Tue, 24 Sep 2024 15:34:38 +0200 Subject: [PATCH 23/26] Update pgd-settings.mdx (#6086) * Update pgd-settings.mdx rewording * Update product_docs/docs/pgd/5/reference/pgd-settings.mdx Co-authored-by: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> * Update product_docs/docs/pgd/5/reference/pgd-settings.mdx Co-authored-by: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> * Update product_docs/docs/pgd/5/reference/pgd-settings.mdx * Update product_docs/docs/pgd/5/reference/pgd-settings.mdx --------- Co-authored-by: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> --- product_docs/docs/pgd/5/reference/pgd-settings.mdx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/product_docs/docs/pgd/5/reference/pgd-settings.mdx b/product_docs/docs/pgd/5/reference/pgd-settings.mdx index 08633f62198..1d68c675cdc 100644 --- a/product_docs/docs/pgd/5/reference/pgd-settings.mdx +++ b/product_docs/docs/pgd/5/reference/pgd-settings.mdx @@ -51,10 +51,9 @@ PGD can't replicate `UPDATE` and `DELETE` operations on tables without a for the table is `FULL`, either by table-specific configuration or by `bdr.default_replica_identity`. -If `bdr.default_replica_identity` is `default` and is a `UNIQUE` -constraint is on the table, it isn't automatically picked up as `REPLICA IDENTITY`. -You need to set it explicitly when creating the table or after, as described -previously. +If `bdr.default_replica_identity` is `default` and there is a `UNIQUE` +constraint included in the table definition, it won't be automatically picked up as `REPLICA IDENTITY`. +You need to set the `REPLICA IDENTITY` explicitly using `ALTER TABLE ... REPLICA IDENTITY ...`. Setting the replica identity of tables to `full` increases the volume of WAL written and the amount of data replicated on the wire for the table. From 8e2e8a63d4432378c23a4ebc363c9aa7cdc9dd9c Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan <126472455+djw-m@users.noreply.github.com> Date: Tue, 24 Sep 2024 16:04:42 +0100 Subject: [PATCH 24/26] Sidebar KB entries updated (#6087) Signed-off-by: Dj Walker-Morgan --- src/components/index-sub-nav.js | 2 +- src/components/side-navigation.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/index-sub-nav.js b/src/components/index-sub-nav.js index 75a21adb926..e7bc38d9bab 100644 --- a/src/components/index-sub-nav.js +++ b/src/components/index-sub-nav.js @@ -13,7 +13,7 @@ const IndexSubNav = () => (
    EDB Home - + Knowledge Base and Technical Alerts diff --git a/src/components/side-navigation.js b/src/components/side-navigation.js index 37bf8361670..76973eee464 100644 --- a/src/components/side-navigation.js +++ b/src/components/side-navigation.js @@ -35,7 +35,7 @@ const SideNavigationFooter = ({ hideKBLink = false }) => (

      {!hideKBLink && ( - + Knowledge Base and Technical Alerts )} From 40166c9092f65ec334f7d0bc898868f221a7b8ea Mon Sep 17 00:00:00 2001 From: Betsy Gitelman Date: Tue, 24 Sep 2024 11:36:42 -0400 Subject: [PATCH 25/26] Apply suggestions from code review --- advocacy_docs/community/contributing/styleguide.mdx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/advocacy_docs/community/contributing/styleguide.mdx b/advocacy_docs/community/contributing/styleguide.mdx index f76462cc9e9..d6867f9d39b 100644 --- a/advocacy_docs/community/contributing/styleguide.mdx +++ b/advocacy_docs/community/contributing/styleguide.mdx @@ -661,16 +661,16 @@ because the symbol can affect how search engines index and find pages. ## Frontmatter -The frontmatter is located at the top of every markdown page, and allows you to specify metadata and options in YAML language. Frontmatter lets you control how a page will render. +The frontmatter is located at the top of every Markdown page and allows you to specify metadata and options in YAML language. Frontmatter lets you control how a page renders. -Ensure your page, at minimum, includes a `title` and `description` as metadata. It can include other metadata such as `navTitle`, `deepToC`, etc. +Ensure your page, at minimum, includes a `title` and `description` as metadata. It can include other metadata such as `navTitle`, `deepToC`, and so on. ```yaml --- -title: Working with the Repo -description: Step by step instructions to install and use the docs repo. +title: Working with the repo +description: Step-by-step instructions to install and use the docs repo. --- ``` !!!note - Ensure the `description` has a final stop, even if it isn't a full grammatical sentence. Descriptions are used to dynamically build a summary for each section in `index` pages. Since all descriptions are then displayed next to each other, add a full stop to ensure visual consistency. + Ensure the `description` has a final stop (period), even if it isn't a full grammatical sentence. Descriptions are used to dynamically build a summary for each section in `index` pages. Since all descriptions are then displayed next to each other, add a full stop to ensure visual consistency. From 113820beae49405cb1d9ab472646c2a9950fff36 Mon Sep 17 00:00:00 2001 From: Dj Walker-Morgan Date: Tue, 24 Sep 2024 17:46:46 +0100 Subject: [PATCH 26/26] Refreshed known issues for BDR-5373 Signed-off-by: Dj Walker-Morgan --- product_docs/docs/pgd/5/known_issues.mdx | 74 ++++++++---------------- 1 file changed, 23 insertions(+), 51 deletions(-) diff --git a/product_docs/docs/pgd/5/known_issues.mdx b/product_docs/docs/pgd/5/known_issues.mdx index 6a01706e7c9..e876f07a0da 100644 --- a/product_docs/docs/pgd/5/known_issues.mdx +++ b/product_docs/docs/pgd/5/known_issues.mdx @@ -8,69 +8,41 @@ These known issues are tracked in PGD's ticketing system and are expected to be resolved in a future release. -- If the resolver for the `update_origin_change` conflict - is set to `skip`, `synchronous_commit=remote_apply` is used, and - concurrent updates of the same row are repeatedly applied on two - different nodes, then one of the update statements might hang due - to a deadlock with the PGD writer. As mentioned in - [Conflicts](consistency/conflicts/), `skip` isn't the default - resolver for the `update_origin_change` conflict, and this - combination isn't intended to be used in production. It discards - one of the two conflicting updates based on the order of arrival - on that node, which is likely to cause a divergent cluster. - In the rare situation that you do choose to use the `skip` - conflict resolver, note the issue with the use of the - `remote_apply` mode. +- If the resolver for the `update_origin_change` conflict is set to `skip`, `synchronous_commit=remote_apply` is used, and concurrent updates of the same row are repeatedly applied on two different nodes, then one of the update statements might hang due +to a deadlock with the PGD writer. +As mentioned in [Conflicts](consistency/conflicts/), `skip` isn't the default resolver for the `update_origin_change` conflict, and this combination isn't intended to be used in production. +It discards one of the two conflicting updates based on the order of arrival on that node, which is likely to cause a divergent cluster. +In the rare situation that you do choose to use the `skip` conflict resolver, note the issue with the use of the `remote_apply` mode. - The Decoding Worker feature doesn't work with CAMO/Eager/Group Commit. - Installations using CAMO/Eager/Group Commit must keep `enable_wal_decoder` - disabled. +Installations using CAMO/Eager/Group Commit must keep `enable_wal_decoder` disabled. -- Lag Control doesn't adjust commit delay in any way on a fully - isolated node, that is, in case all other nodes are unreachable or not - operational. As soon as at least one node is connected, replication - Lag Control picks up its work and adjusts the PGD commit delay - again. +- Lag Control doesn't adjust commit delay in any way on a fully isolated node, that's in case all other nodes are unreachable or not operational. +As soon as at least one node connects, replication Lag Control picks up its work and adjusts the PGD commit delay again. -- For time-based Lag Control, PGD currently uses the lag time (measured - by commit timestamps) rather than the estimated catchup time that's - based on historic apply rates. +- For time-based Lag Control, PGD currently uses the lag time, measured by commit timestamps, rather than the estimated catch up time that's based on historic apply rates. - Changing the CAMO partners in a CAMO pair isn't currently possible. - It's possible only to add or remove a pair. - Adding or removing a pair doesn't require a restart of Postgres or even a - reload of the configuration. +It's possible only to add or remove a pair. +Adding or removing a pair doesn't require a restart of Postgres or even a reload of the configuration. - Group Commit can't be combined with [CAMO](durability/camo/). -- Transactions using Eager Replication can't yet execute DDL. The TRUNCATE - command is allowed. +- Transactions using Eager Replication can't yet execute DDL. The TRUNCATE command is allowed. -- Parallel Apply isn't currently supported in combination with Group Commit. Make sure to disable it when using Group Commit by either: - - Setting `num_writers` to 1 for the node group using [`bdr.alter_node_group_config`](/pgd/latest/reference/nodes-management-interfaces/#bdralter_node_group_config). - - Using the GUC `bdr.writers_per_subscription`. See [Configuration of generic replication](/pgd/latest/reference/pgd-settings/#generic-replication). +- Parallel Apply isn't currently supported in combination with Group Commit. Make sure to disable it when using Group Commit by either (a) Setting `num_writers` to 1 for the node group using [`bdr.alter_node_group_config`](/pgd/latest/reference/nodes-management-interfaces/#bdralter_node_group_config) or (b) using the GUC [`bdr.writers_per_subscription`](/pgd/latest/reference/pgd-settings#bdrwriters_per_subscription). See [Configuration of generic replication](/pgd/latest/reference/pgd-settings#generic-replication). -- There currently is no protection against altering or removing a commit - scope. Running transactions in a commit scope that's concurrently being - altered or removed can lead to the transaction blocking or replication - stalling completely due to an error on the downstream node attempting to - apply the transaction. Make sure that any transactions using a specific commit - scope have finished before altering or removing it. +- There currently is no protection against altering or removing a commit scope. +Running transactions in a commit scope that's concurrently being altered or removed can lead to the transaction blocking or replication stalling completely due to an error on the downstream node attempting to apply the transaction. +Make sure that any transactions using a specific commit scope have finished before altering or removing it. -- The [PGD CLI](cli) can return stale data on the state of the cluster if it's - still connecting to nodes that were previously parted from the cluster. Edit - the [`pgd-cli-config.yml`](cli/configuring_cli/#using-a-configuration-file) - file, or change your - [`--dsn`](cli/configuring_cli/#using-database-connection-strings-in-the-command-line) - settings to ensure only active nodes in the cluster are listed for - connection. +- The [PGD CLI](cli) can return stale data on the state of the cluster if it's still connecting to nodes that were previously parted from the cluster. +Edit the [`pgd-cli-config.yml`](cli/configuring_cli/#using-a-configuration-file) file, or change your [`--dsn`](cli/configuring_cli/#using-database-connection-strings-in-the-command-line) settings to ensure only active nodes in the cluster are listed for connection. -- When using - [`bdr.add_commit_scope`](/pgd/latest/reference/functions#bdradd_commit_scope), - if a new commit scope is added that has the same name as a commit scope on - any group, then the commit scope silently overwrites the commit scope but - retains the original group the scope was associated with (if any). To modify - a commit scope safely, use - [`bdr.alter_commit_scope`](/pgd/latest/reference/functions#bdralter_commit_scope). +- When using [`bdr.add_commit_scope`](/pgd/latest/reference/functions#bdradd_commit_scope), if a new commit scope is added that has the same name as a commit scope on any group, then the commit scope silently overwrites the commit scope but retains the original group the scope was associated with (if any). +To modify a commit scope safely, use [`bdr.alter_commit_scope`](/pgd/latest/reference/functions#bdralter_commit_scope). + +- Tables configured with `REPLICA IDENTITY FULL` and include `box`, `polygon` or `json` types in their columns are using PGD aren't able to be replicated. +You can mitigate this issue by configuring a primary key for `REPLICA IDENTITY` to use or, for `json` columns only, using the `jsonb` type instead. Details of other design or implementation [limitations](planning/limitations) are also available.