[Developer] #424 support ORDS handler source editing

This commit is contained in:
devmrko
2026-06-23 15:09:23 +09:00
parent d9a676d706
commit a542a7b735
8 changed files with 158 additions and 16 deletions

View File

@@ -0,0 +1,9 @@
package com.cloudhandson.vpdbackoffice.domain.ords;
import jakarta.validation.constraints.NotBlank;
public record OrdsHandlerUpdateCommand(
long handlerId,
@NotBlank String source
) {
}

View File

@@ -1,7 +1,11 @@
package com.cloudhandson.vpdbackoffice.domain.ords;
import java.util.Locale;
public record OrdsHandlerView(
Long handlerId,
String schemaName,
String parsingSchema,
String moduleName,
String basePath,
String template,
@@ -15,4 +19,8 @@ public record OrdsHandlerView(
public String fullPath() {
return "/ords/" + schemaName + "/" + basePath + template;
}
public boolean plsqlEditable() {
return sourceType != null && sourceType.toLowerCase(Locale.ROOT).contains("plsql");
}
}

View File

@@ -3,11 +3,14 @@ package com.cloudhandson.vpdbackoffice.mapper;
import com.cloudhandson.vpdbackoffice.domain.ords.OrdsHandlerView;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface OrdsMetadataMapper {
List<OrdsHandlerView> findHandlers();
OrdsHandlerView findHandler(@Param("handlerId") long handlerId);
String findHandlerPackageSource();
}

View File

@@ -1,24 +1,32 @@
package com.cloudhandson.vpdbackoffice.service;
import com.cloudhandson.vpdbackoffice.domain.ords.OrdsHandlerUpdateCommand;
import com.cloudhandson.vpdbackoffice.domain.ords.OrdsHandlerView;
import com.cloudhandson.vpdbackoffice.mapper.OrdsMetadataMapper;
import java.util.List;
import java.util.Locale;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class OrdsMetadataService {
private final OrdsMetadataMapper mapper;
private final JdbcTemplate jdbcTemplate;
public OrdsMetadataService(OrdsMetadataMapper mapper) {
public OrdsMetadataService(OrdsMetadataMapper mapper, JdbcTemplate jdbcTemplate) {
this.mapper = mapper;
this.jdbcTemplate = jdbcTemplate;
}
public List<OrdsHandlerView> findHandlers() {
String packageSource = mapper.findHandlerPackageSource();
return mapper.findHandlers().stream()
.map(handler -> new OrdsHandlerView(
handler.handlerId(),
handler.schemaName(),
handler.parsingSchema(),
handler.moduleName(),
handler.basePath(),
handler.template(),
@@ -30,4 +38,37 @@ public class OrdsMetadataService {
))
.toList();
}
@Transactional
public void updateHandlerSource(OrdsHandlerUpdateCommand command) {
if (command.source() == null || command.source().isBlank()) {
throw new AppException("ORDS Handler Source는 필수입니다.");
}
OrdsHandlerView handler = mapper.findHandler(command.handlerId());
if (handler == null) {
throw new AppException("수정할 ORDS Handler를 찾을 수 없습니다.");
}
String sourceType = handler.sourceType() == null ? "" : handler.sourceType().toLowerCase(Locale.ROOT);
if (!sourceType.contains("plsql")) {
throw new AppException("현재는 PL/SQL ORDS Handler만 수정할 수 있습니다: " + handler.sourceType());
}
String currentUser = jdbcTemplate.queryForObject("SELECT USER FROM dual", String.class);
if (currentUser == null || !currentUser.equalsIgnoreCase(handler.parsingSchema())) {
throw new AppException("ORDS Handler 수정은 parsing schema로 DB에 연결했을 때만 가능합니다. 현재 연결 사용자: "
+ currentUser + ", Handler parsing schema: " + handler.parsingSchema());
}
jdbcTemplate.update("""
BEGIN
ORDS.DEFINE_HANDLER(
p_module_name => ?,
p_pattern => ?,
p_method => ?,
p_source_type => ORDS.source_type_plsql,
p_source => ?,
p_items_per_page => 0
);
COMMIT;
END;
""", handler.moduleName(), handler.template(), handler.method(), command.source());
}
}

View File

@@ -1,9 +1,15 @@
package com.cloudhandson.vpdbackoffice.web;
import com.cloudhandson.vpdbackoffice.domain.ords.OrdsHandlerUpdateCommand;
import com.cloudhandson.vpdbackoffice.service.AppException;
import com.cloudhandson.vpdbackoffice.service.OrdsMetadataService;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
@Controller
public class OrdsHandlerController {
@@ -19,4 +25,22 @@ public class OrdsHandlerController {
model.addAttribute("handlers", ordsMetadataService.findHandlers());
return "ords-handlers";
}
@PostMapping("/ords-handlers/update")
public String update(
@RequestParam long handlerId,
@RequestParam String source,
RedirectAttributes redirectAttributes
) {
try {
ordsMetadataService.updateHandlerSource(new OrdsHandlerUpdateCommand(handlerId, source));
redirectAttributes.addFlashAttribute("message", "ORDS Handler Source를 저장했습니다.");
} catch (AppException exception) {
redirectAttributes.addFlashAttribute("errorMessage", exception.getMessage());
} catch (DataAccessException exception) {
RuntimeErrorMessage error = RuntimeErrorMessages.dataAccess(exception);
redirectAttributes.addFlashAttribute("errorMessage", error.message());
}
return "redirect:/ords-handlers";
}
}