Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions .github/workflows/test_worktree_build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
name: Test Git Worktree Build

on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to test'
required: false
default: 'develop'

jobs:
test-worktree:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ github.event.inputs.branch }}
fetch-depth: 0

- name: Set up JDK 11
uses: actions/setup-java@v4
with:
java-version: "11"
distribution: "adopt"
cache: maven

- name: Create git worktree
run: git worktree add --detach ../obp-api-worktree HEAD

- name: Build from worktree
working-directory: ../obp-api-worktree
run: |
set -o pipefail
MAVEN_OPTS="-Xmx3G -Xss2m -XX:MaxMetaspaceSize=1G" mvn clean package -DskipTests 2>&1 | tee "$GITHUB_WORKSPACE/worktree-build.log"

- name: Verify git.properties was generated
run: |
PROPS_FILE="../obp-api-worktree/obp-api/target/classes/git.properties"
if [ ! -f "$PROPS_FILE" ]; then
echo "FAIL: git.properties not found"
exit 1
fi
echo "Contents of git.properties:"
cat "$PROPS_FILE"

check_field() {
local field=$1
local value
value=$(grep "^${field}=" "$PROPS_FILE" | cut -d'=' -f2-)
if [ -z "$value" ]; then
echo "FAIL: $field is empty or missing"
exit 1
fi
echo "OK: $field=$value"
}

check_field "git.commit.id"
check_field "git.branch"
check_field "git.build.time"

- name: Upload build log
if: always()
uses: actions/upload-artifact@v4
with:
name: worktree-build-log
if-no-files-found: ignore
path: worktree-build.log

- name: Clean up worktree
if: always()
run: git worktree remove ../obp-api-worktree --force || true
3 changes: 2 additions & 1 deletion obp-api/src/main/scala/code/api/constant/constant.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import code.api.util.{APIUtil, ErrorMessages}
import code.api.cache.Redis
import code.util.Helper.MdcLoggable
import com.openbankproject.commons.util.ApiStandards
import net.liftweb.common.Box
import net.liftweb.util.Props


Expand Down Expand Up @@ -137,7 +138,7 @@ object Constant extends MdcLoggable {

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

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

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

Expand Down
14 changes: 11 additions & 3 deletions obp-api/src/main/scala/code/api/util/APIUtil.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3032,14 +3032,22 @@ object APIUtil extends MdcLoggable with CustomJsonFormats{
}

private def getFilteredOrFullErrorMessage[T](e: Box[Throwable]): JsonResponse = {
def findObpMessage(t: Throwable): Option[String] = {
if (t == null) None
else Option(t.getMessage).filter(_.startsWith("OBP-"))
.orElse(findObpMessage(t.getCause))
}
getPropsAsBoolValue("display_internal_errors", false) match {
case true => // Show all error in a chain
errorJsonResponse(
AnUnspecifiedOrInternalErrorOccurred +
e.map(error => " -> " + error.getCause() + " -> " + error.getStackTrace().mkString(";")).getOrElse("")
e.map { error =>
val leadMessage = findObpMessage(error).getOrElse(AnUnspecifiedOrInternalErrorOccurred)
leadMessage + " -> " + error.getStackTrace().mkString(";")
}.getOrElse(AnUnspecifiedOrInternalErrorOccurred)
)
case false => // Do not display internal errors
errorJsonResponse(AnUnspecifiedOrInternalErrorOccurred)
val obpMessage = e.flatMap(error => findObpMessage(error))
errorJsonResponse(obpMessage.getOrElse(AnUnspecifiedOrInternalErrorOccurred))
}
}

Expand Down
2 changes: 1 addition & 1 deletion obp-api/src/main/scala/code/api/util/Glossary.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2084,7 +2084,7 @@ object Glossary extends MdcLoggable {
|
""")

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

// OAuth2 documentation is sourced from OpenAPI31JSONFactory (the source of truth for auth docs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,17 @@ object RabbitMQConnectionPool {
private val pool = new GenericObjectPool[Connection](new RabbitMQConnectionFactory(), poolConfig)

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

// Method to return a connection to the pool
def returnConnection(conn: Connection): Unit = pool.returnObject(conn)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,43 +90,46 @@ object RabbitMQUtils extends MdcLoggable{
def sendRequestUndGetResponseFromRabbitMQ[T: Manifest](messageId: String, outBound: TopicTrait): Future[Box[T]] = {

val rabbitRequestJsonString: String = write(outBound) // convert OutBound to json string

val connection = RabbitMQConnectionPool.borrowConnection()
// Check if queue already exists using a temporary channel (passive declare closes channel on failure)
val queueExists = try {
val tempChannel = connection.createChannel()
try {
tempChannel.queueDeclarePassive(RPC_QUEUE_NAME)
true
} finally {
if (tempChannel.isOpen) tempChannel.close()
}
} catch {
case _: java.io.IOException => false
}

val channel = connection.createChannel() // channel is not thread safe, so we always create new channel for each message.
// Only declare queue if it doesn't already exist (avoids argument conflicts with external adapters)
if (!queueExists) {
channel.queueDeclare(
RPC_QUEUE_NAME, // Queue name
true, // durable: non-persis, here set durable = true
false, // exclusive: non-excl4, here set exclusive = false
false, // autoDelete: delete, here set autoDelete = false
rpcQueueArgs // extra arguments,
)
}

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

val rabbitResponseJsonFuture = {
try {
val connection = RabbitMQConnectionPool.borrowConnection()
connectionOpt = Some(connection)
// Check if queue already exists using a temporary channel (passive declare closes channel on failure)
val queueExists = try {
val tempChannel = connection.createChannel()
try {
tempChannel.queueDeclarePassive(RPC_QUEUE_NAME)
true
} finally {
if (tempChannel.isOpen) tempChannel.close()
}
} catch {
case _: java.io.IOException => false
}

val channel = connection.createChannel() // channel is not thread safe, so we always create new channel for each message.
// Only declare queue if it doesn't already exist (avoids argument conflicts with external adapters)
if (!queueExists) {
channel.queueDeclare(
RPC_QUEUE_NAME, // Queue name
true, // durable: non-persis, here set durable = true
false, // exclusive: non-excl4, here set exclusive = false
false, // autoDelete: delete, here set autoDelete = false
rpcQueueArgs // extra arguments,
)
}

val replyQueueName:String = channel.queueDeclare(
s"${RPC_REPLY_TO_QUEUE_NAME_PREFIX}_${messageId.replace("obp_","")}_${UUID.randomUUID.toString}", // Queue name, it will be a unique name for each queue
false, // durable: non-persis, here set durable = false
true, // exclusive: non-excl4, here set exclusive = true
true, // autoDelete: delete, here set autoDelete = true
rpcReplyToQueueArgs // extra arguments,
).getQueue

logger.debug(s"${RabbitMQConnector_vOct2024.toString} outBoundJson: $messageId = $rabbitRequestJsonString")
logger.info(s"[RabbitMQ] Sending message to queue: $RPC_QUEUE_NAME, messageId: $messageId, replyTo: $replyQueueName")

Expand All @@ -144,13 +147,15 @@ object RabbitMQUtils extends MdcLoggable{
channel.basicConsume(replyQueueName, true, responseCallback, cancelCallback)
responseCallback.take()
} catch {
case e: Throwable =>{
case e: RuntimeException if e.getMessage != null && e.getMessage.startsWith("OBP-") =>
logger.debug(s"${RabbitMQConnector_vOct2024.toString} inBoundJson exception: $messageId = ${e}")
throw e
case e: Throwable =>
logger.debug(s"${RabbitMQConnector_vOct2024.toString} inBoundJson exception: $messageId = ${e}")
throw new RuntimeException(s"$AdapterUnknownError Please Check Adapter Side! Details: ${e.getMessage}")//TODO error handling to API level
}
}
}
finally {
RabbitMQConnectionPool.returnConnection(connection)
connectionOpt.foreach(RabbitMQConnectionPool.returnConnection)
}
}
rabbitResponseJsonFuture.map(rabbitResponseJsonString =>logger.debug(s"${RabbitMQConnector_vOct2024.toString} inBoundJson: $messageId = $rabbitResponseJsonString" ))
Expand Down
Loading
Loading