package com.cloudhandson.vpdbackoffice.service; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.TextNode; import java.sql.CallableStatement; import java.sql.Clob; import java.sql.PreparedStatement; import java.sql.ResultSet; import org.springframework.jdbc.core.ConnectionCallback; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Service; /** JDBC implementation shared with the standalone HMM MCP facade. */ @Service public class JdbcHmmAiAgentToolRunner implements HmmAiAgentToolRunner { private final JdbcTemplate jdbcTemplate; private final ObjectMapper objectMapper; public JdbcHmmAiAgentToolRunner(JdbcTemplate jdbcTemplate, ObjectMapper objectMapper) { this.jdbcTemplate = jdbcTemplate; this.objectMapper = objectMapper; } @Override public JsonNode run( String toolName, com.fasterxml.jackson.databind.node.ObjectNode input, String bearerToken ) { try { String request = objectMapper.writeValueAsString(input); String response = jdbcTemplate.execute((ConnectionCallback) connection -> { boolean contextSet = false; try { try (CallableStatement statement = connection.prepareCall( "BEGIN ADMIN.HMM_ACCESS_CTX_PKG.SET_USER_BY_BEARER(?); END;")) { statement.setString(1, bearerToken); statement.execute(); contextSet = true; } try (PreparedStatement statement = connection.prepareStatement(""" SELECT DBMS_CLOUD_AI_AGENT.RUN_TOOL(?, TO_CLOB(?)) FROM dual """)) { statement.setString(1, toolName); statement.setString(2, request); try (ResultSet resultSet = statement.executeQuery()) { if (!resultSet.next()) { return ""; } Clob clob = resultSet.getClob(1); return clob == null ? "" : clob.getSubString(1, (int) clob.length()); } } } finally { if (contextSet) { try (CallableStatement statement = connection.prepareCall( "BEGIN ADMIN.HMM_ACCESS_CTX_PKG.CLEAR_USER; END;")) { statement.execute(); } } } }); if (response == null || response.isBlank()) { return objectMapper.createObjectNode(); } try { return objectMapper.readTree(response); } catch (Exception ignored) { return TextNode.valueOf(response); } } catch (Exception exception) { throw new AppException("HMM AI Agent Tool 실행에 실패했습니다: " + exception.getMessage()); } } }