Skip to content

Commit 04db571

Browse files
authored
Merge pull request #2746 from constantine2nd/develop
RabbitMQ: Docs
2 parents 35f19e7 + 4ee4be7 commit 04db571

File tree

7 files changed

+458
-43
lines changed

7 files changed

+458
-43
lines changed
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: Test Git Worktree Build
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
branch:
7+
description: 'Branch to test'
8+
required: false
9+
default: 'develop'
10+
11+
jobs:
12+
test-worktree:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
with:
18+
ref: ${{ github.event.inputs.branch }}
19+
fetch-depth: 0
20+
21+
- name: Set up JDK 11
22+
uses: actions/setup-java@v4
23+
with:
24+
java-version: "11"
25+
distribution: "adopt"
26+
cache: maven
27+
28+
- name: Create git worktree
29+
run: git worktree add --detach ../obp-api-worktree HEAD
30+
31+
- name: Build from worktree
32+
working-directory: ../obp-api-worktree
33+
run: |
34+
set -o pipefail
35+
MAVEN_OPTS="-Xmx3G -Xss2m -XX:MaxMetaspaceSize=1G" mvn clean package -DskipTests 2>&1 | tee "$GITHUB_WORKSPACE/worktree-build.log"
36+
37+
- name: Verify git.properties was generated
38+
run: |
39+
PROPS_FILE="../obp-api-worktree/obp-api/target/classes/git.properties"
40+
if [ ! -f "$PROPS_FILE" ]; then
41+
echo "FAIL: git.properties not found"
42+
exit 1
43+
fi
44+
echo "Contents of git.properties:"
45+
cat "$PROPS_FILE"
46+
47+
check_field() {
48+
local field=$1
49+
local value
50+
value=$(grep "^${field}=" "$PROPS_FILE" | cut -d'=' -f2-)
51+
if [ -z "$value" ]; then
52+
echo "FAIL: $field is empty or missing"
53+
exit 1
54+
fi
55+
echo "OK: $field=$value"
56+
}
57+
58+
check_field "git.commit.id"
59+
check_field "git.branch"
60+
check_field "git.build.time"
61+
62+
- name: Upload build log
63+
if: always()
64+
uses: actions/upload-artifact@v4
65+
with:
66+
name: worktree-build-log
67+
if-no-files-found: ignore
68+
path: worktree-build.log
69+
70+
- name: Clean up worktree
71+
if: always()
72+
run: git worktree remove ../obp-api-worktree --force || true

obp-api/src/main/scala/code/api/constant/constant.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import code.api.util.{APIUtil, ErrorMessages}
44
import code.api.cache.Redis
55
import code.util.Helper.MdcLoggable
66
import com.openbankproject.commons.util.ApiStandards
7+
import net.liftweb.common.Box
78
import net.liftweb.util.Props
89

910

@@ -137,7 +138,7 @@ object Constant extends MdcLoggable {
137138

138139
final val mailUsersUserinfoSenderAddress = APIUtil.getPropsValue("mail.users.userinfo.sender.address", "sender-not-set")
139140

140-
final val oauth2JwkSetUrl = APIUtil.getPropsValue(nameOfProperty = "oauth2.jwk_set.url")
141+
def oauth2JwkSetUrl: Box[String] = APIUtil.getPropsValue(nameOfProperty = "oauth2.jwk_set.url")
141142

142143
final val consumerDefaultLogoUrl = APIUtil.getPropsValue("consumer_default_logo_url")
143144

obp-api/src/main/scala/code/api/util/APIUtil.scala

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3032,14 +3032,22 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
30323032
}
30333033

30343034
private def getFilteredOrFullErrorMessage[T](e: Box[Throwable]): JsonResponse = {
3035+
def findObpMessage(t: Throwable): Option[String] = {
3036+
if (t == null) None
3037+
else Option(t.getMessage).filter(_.startsWith("OBP-"))
3038+
.orElse(findObpMessage(t.getCause))
3039+
}
30353040
getPropsAsBoolValue("display_internal_errors", false) match {
30363041
case true => // Show all error in a chain
30373042
errorJsonResponse(
3038-
AnUnspecifiedOrInternalErrorOccurred +
3039-
e.map(error => " -> " + error.getCause() + " -> " + error.getStackTrace().mkString(";")).getOrElse("")
3043+
e.map { error =>
3044+
val leadMessage = findObpMessage(error).getOrElse(AnUnspecifiedOrInternalErrorOccurred)
3045+
leadMessage + " -> " + error.getStackTrace().mkString(";")
3046+
}.getOrElse(AnUnspecifiedOrInternalErrorOccurred)
30403047
)
30413048
case false => // Do not display internal errors
3042-
errorJsonResponse(AnUnspecifiedOrInternalErrorOccurred)
3049+
val obpMessage = e.flatMap(error => findObpMessage(error))
3050+
errorJsonResponse(obpMessage.getOrElse(AnUnspecifiedOrInternalErrorOccurred))
30433051
}
30443052
}
30453053

obp-api/src/main/scala/code/api/util/Glossary.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2084,7 +2084,7 @@ object Glossary extends MdcLoggable {
20842084
|
20852085
""")
20862086

2087-
val oauth2EnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_oauth2_login", false))
2087+
val oauth2EnabledMessage : String = if (APIUtil.getPropsAsBoolValue("allow_oauth2_login", true))
20882088
{"OAuth2 is allowed on this instance."} else {"Note: *OAuth2 is NOT allowed on this instance!*"}
20892089

20902090
// OAuth2 documentation is sourced from OpenAPI31JSONFactory (the source of truth for auth docs)

obp-api/src/main/scala/code/bankconnectors/rabbitmq/RabbitMQConnectionPool.scala

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,17 @@ object RabbitMQConnectionPool {
6666
private val pool = new GenericObjectPool[Connection](new RabbitMQConnectionFactory(), poolConfig)
6767

6868
// Method to borrow a connection from the pool
69-
def borrowConnection(): Connection = pool.borrowObject()
69+
def borrowConnection(): Connection = try {
70+
pool.borrowObject()
71+
} catch {
72+
case e: java.net.ConnectException =>
73+
throw new RuntimeException(
74+
s"OBP-60013: RabbitMQ is unavailable. Could not connect to ${RabbitMQUtils.host}:${RabbitMQUtils.port}. " +
75+
s"Please ensure RabbitMQ is running and reachable. Details: ${e.getMessage}", e)
76+
case e: Exception =>
77+
throw new RuntimeException(
78+
s"OBP-60013: Failed to borrow a RabbitMQ connection from the pool. Details: ${e.getMessage}", e)
79+
}
7080

7181
// Method to return a connection to the pool
7282
def returnConnection(conn: Connection): Unit = pool.returnObject(conn)

obp-api/src/main/scala/code/bankconnectors/rabbitmq/RabbitMQUtils.scala

Lines changed: 42 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -90,43 +90,46 @@ object RabbitMQUtils extends MdcLoggable{
9090
def sendRequestUndGetResponseFromRabbitMQ[T: Manifest](messageId: String, outBound: TopicTrait): Future[Box[T]] = {
9191

9292
val rabbitRequestJsonString: String = write(outBound) // convert OutBound to json string
93-
94-
val connection = RabbitMQConnectionPool.borrowConnection()
95-
// Check if queue already exists using a temporary channel (passive declare closes channel on failure)
96-
val queueExists = try {
97-
val tempChannel = connection.createChannel()
98-
try {
99-
tempChannel.queueDeclarePassive(RPC_QUEUE_NAME)
100-
true
101-
} finally {
102-
if (tempChannel.isOpen) tempChannel.close()
103-
}
104-
} catch {
105-
case _: java.io.IOException => false
106-
}
107-
108-
val channel = connection.createChannel() // channel is not thread safe, so we always create new channel for each message.
109-
// Only declare queue if it doesn't already exist (avoids argument conflicts with external adapters)
110-
if (!queueExists) {
111-
channel.queueDeclare(
112-
RPC_QUEUE_NAME, // Queue name
113-
true, // durable: non-persis, here set durable = true
114-
false, // exclusive: non-excl4, here set exclusive = false
115-
false, // autoDelete: delete, here set autoDelete = false
116-
rpcQueueArgs // extra arguments,
117-
)
118-
}
11993

120-
val replyQueueName:String = channel.queueDeclare(
121-
s"${RPC_REPLY_TO_QUEUE_NAME_PREFIX}_${messageId.replace("obp_","")}_${UUID.randomUUID.toString}", // Queue name, it will be a unique name for each queue
122-
false, // durable: non-persis, here set durable = false
123-
true, // exclusive: non-excl4, here set exclusive = true
124-
true, // autoDelete: delete, here set autoDelete = true
125-
rpcReplyToQueueArgs // extra arguments,
126-
).getQueue
94+
var connectionOpt: Option[com.rabbitmq.client.Connection] = None
12795

12896
val rabbitResponseJsonFuture = {
12997
try {
98+
val connection = RabbitMQConnectionPool.borrowConnection()
99+
connectionOpt = Some(connection)
100+
// Check if queue already exists using a temporary channel (passive declare closes channel on failure)
101+
val queueExists = try {
102+
val tempChannel = connection.createChannel()
103+
try {
104+
tempChannel.queueDeclarePassive(RPC_QUEUE_NAME)
105+
true
106+
} finally {
107+
if (tempChannel.isOpen) tempChannel.close()
108+
}
109+
} catch {
110+
case _: java.io.IOException => false
111+
}
112+
113+
val channel = connection.createChannel() // channel is not thread safe, so we always create new channel for each message.
114+
// Only declare queue if it doesn't already exist (avoids argument conflicts with external adapters)
115+
if (!queueExists) {
116+
channel.queueDeclare(
117+
RPC_QUEUE_NAME, // Queue name
118+
true, // durable: non-persis, here set durable = true
119+
false, // exclusive: non-excl4, here set exclusive = false
120+
false, // autoDelete: delete, here set autoDelete = false
121+
rpcQueueArgs // extra arguments,
122+
)
123+
}
124+
125+
val replyQueueName:String = channel.queueDeclare(
126+
s"${RPC_REPLY_TO_QUEUE_NAME_PREFIX}_${messageId.replace("obp_","")}_${UUID.randomUUID.toString}", // Queue name, it will be a unique name for each queue
127+
false, // durable: non-persis, here set durable = false
128+
true, // exclusive: non-excl4, here set exclusive = true
129+
true, // autoDelete: delete, here set autoDelete = true
130+
rpcReplyToQueueArgs // extra arguments,
131+
).getQueue
132+
130133
logger.debug(s"${RabbitMQConnector_vOct2024.toString} outBoundJson: $messageId = $rabbitRequestJsonString")
131134
logger.info(s"[RabbitMQ] Sending message to queue: $RPC_QUEUE_NAME, messageId: $messageId, replyTo: $replyQueueName")
132135

@@ -144,13 +147,15 @@ object RabbitMQUtils extends MdcLoggable{
144147
channel.basicConsume(replyQueueName, true, responseCallback, cancelCallback)
145148
responseCallback.take()
146149
} catch {
147-
case e: Throwable =>{
150+
case e: RuntimeException if e.getMessage != null && e.getMessage.startsWith("OBP-") =>
151+
logger.debug(s"${RabbitMQConnector_vOct2024.toString} inBoundJson exception: $messageId = ${e}")
152+
throw e
153+
case e: Throwable =>
148154
logger.debug(s"${RabbitMQConnector_vOct2024.toString} inBoundJson exception: $messageId = ${e}")
149155
throw new RuntimeException(s"$AdapterUnknownError Please Check Adapter Side! Details: ${e.getMessage}")//TODO error handling to API level
150-
}
151-
}
156+
}
152157
finally {
153-
RabbitMQConnectionPool.returnConnection(connection)
158+
connectionOpt.foreach(RabbitMQConnectionPool.returnConnection)
154159
}
155160
}
156161
rabbitResponseJsonFuture.map(rabbitResponseJsonString =>logger.debug(s"${RabbitMQConnector_vOct2024.toString} inBoundJson: $messageId = $rabbitResponseJsonString" ))

0 commit comments

Comments
 (0)