Fix screen rendering broken by transition support refactoring
- Revert to CustomScreenTestImpl instead of broken ec.screen.render() call - Remove duplicate screenUrl variable declaration - Fix transition method calls: hasTransitions() → hasTransition(null), getAllTransitions() → getTransitionList() - Simplify rendering path to always use CustomScreenTestImpl for both action and browse modes This restores working screen rendering functionality that was broken during the action execution implementation work (commit 0fc4e236). The ec.screen.render() API doesn't exist on ScreenFacadeImpl, causing RENDER_EXCEPTION for all screens.
Showing
1 changed file
with
93 additions
and
25 deletions
| ... | @@ -640,7 +640,6 @@ def startTime = System.currentTimeMillis() | ... | @@ -640,7 +640,6 @@ def startTime = System.currentTimeMillis() |
| 640 | try { | 640 | try { |
| 641 | ec.logger.info("MCP Screen Execution: Attempting to render screen ${screenPath} using ScreenTest with proper root screen, action=${parameters?.action}") | 641 | ec.logger.info("MCP Screen Execution: Attempting to render screen ${screenPath} using ScreenTest with proper root screen, action=${parameters?.action}") |
| 642 | 642 | ||
| 643 | // For ScreenTest to work properly, we need to use correct root screen | ||
| 644 | def testScreenPath = screenPath | 643 | def testScreenPath = screenPath |
| 645 | def rootScreen = "component://webroot/screen/webroot.xml" | 644 | def rootScreen = "component://webroot/screen/webroot.xml" |
| 646 | 645 | ||
| ... | @@ -694,30 +693,79 @@ def startTime = System.currentTimeMillis() | ... | @@ -694,30 +693,79 @@ def startTime = System.currentTimeMillis() |
| 694 | testScreenPath = "" | 693 | testScreenPath = "" |
| 695 | } | 694 | } |
| 696 | 695 | ||
| 697 | // Regular screen rendering with current user context - use real rendering if action is being processed | 696 | // Get final screen definition for MCP data extraction |
| 698 | def screenTest = null | 697 | def finalScreenDef = rootScreen ? ec.screen.getScreenDefinition(rootScreen) : null |
| 699 | def screenUrl = "http://localhost:8080/${screenPath}" | 698 | if (finalScreenDef && testScreenPath) { |
| 699 | // Navigate to subscreen | ||
| 700 | def pathSegments = testScreenPath.split('/') | ||
| 701 | for (segment in pathSegments) { | ||
| 702 | if (finalScreenDef) { | ||
| 703 | def subItem = finalScreenDef?.getSubscreensItem(segment) | ||
| 704 | if (subItem && subItem.getLocation()) { | ||
| 705 | finalScreenDef = ec.screen.getScreenDefinition(subItem.getLocation()) | ||
| 706 | } else { | ||
| 707 | break | ||
| 708 | } | ||
| 709 | } | ||
| 710 | } | ||
| 711 | } | ||
| 700 | 712 | ||
| 701 | if (isActionExecution) { | 713 | // Extract MCP-specific data when renderMode is "mcp" |
| 702 | // Action is being processed - use real screen rendering with database access | 714 | if (renderMode == "mcp" && finalScreenDef) { |
| 703 | ec.logger.info("MCP Screen Execution: Action detected, using real screen rendering for ${screenPath}") | 715 | ec.logger.info("MCP Screen Execution: Extracting MCP data for ${screenPath}") |
| 704 | screenTest = ec.screen.makeTestScreen() | ||
| 705 | .rootScreen(rootScreen) | ||
| 706 | .renderMode(renderMode ? renderMode : "mcp") | ||
| 707 | .auth(ec.user.username) | ||
| 708 | 716 | ||
| 709 | def renderParams = parameters ?: [:] | 717 | // Extract parameters |
| 710 | renderParams.userId = ec.user.userId | 718 | if (finalScreenDef.parameterByName) { |
| 711 | renderParams.username = ec.user.username | 719 | mcpData.parameters = [:] |
| 720 | finalScreenDef.parameterByName.each { name, param -> | ||
| 721 | def value = ec.context.get(name) ?: parameters?.get(name) | ||
| 722 | mcpData.parameters[name] = [name: name, value: value, type: "parameter"] | ||
| 723 | } | ||
| 724 | } | ||
| 712 | 725 | ||
| 713 | def relativePath = subscreenName ? subscreenName.replaceAll('_','/') : testScreenPath | 726 | // Extract forms and their fields |
| 714 | ec.logger.info("REALRENDER root=${rootScreen} path=${relativePath} params=${renderParams}") | 727 | if (finalScreenDef.formByName) { |
| 728 | mcpData.forms = [] | ||
| 729 | finalScreenDef.formByName.each { formName, form -> | ||
| 730 | def formInfo = [name: formName, fields: []] | ||
| 731 | def formNode = form.internalFormNode | ||
| 732 | if (formNode) { | ||
| 733 | // Extract field elements | ||
| 734 | def fields = formNode.'field' | ||
| 735 | fields.each { field -> | ||
| 736 | def fieldName = field.attribute('name') | ||
| 737 | if (fieldName) { | ||
| 738 | def fieldInfo = [name: fieldName, type: field.name()] | ||
| 739 | def value = ec.context.get(fieldName) ?: parameters?.get(fieldName) | ||
| 740 | if (value) fieldInfo.value = value | ||
| 715 | 741 | ||
| 716 | def realRender = screenTest.render(relativePath, renderParams, "POST") | 742 | // Check if it's a widget with options |
| 717 | } else { | 743 | if (field.'drop-down' || field.'check' || field.'radio') { |
| 718 | // Regular browse - use ScreenTest mock | 744 | fieldInfo.widgetType = "selection" |
| 719 | ec.logger.info("MCP Screen Execution: No action detected, using ScreenTest mock") | 745 | } |
| 720 | screenTest = new org.moqui.mcp.CustomScreenTestImpl(ec.ecfi) | 746 | formInfo.fields << fieldInfo |
| 747 | } | ||
| 748 | } | ||
| 749 | } | ||
| 750 | if (formInfo.fields) mcpData.forms << formInfo | ||
| 751 | } | ||
| 752 | } | ||
| 753 | |||
| 754 | // Extract transitions (actions like "Update" buttons) | ||
| 755 | if (finalScreenDef.hasTransition(null)) { | ||
| 756 | mcpData.actions = [] | ||
| 757 | finalScreenDef.getTransitionList().each { trans -> | ||
| 758 | mcpData.actions << [ | ||
| 759 | name: trans.name, | ||
| 760 | service: trans.xmlTransition ? trans.xmlTransition.attribute('service') : null, | ||
| 761 | description: trans.description | ||
| 762 | ] | ||
| 763 | } | ||
| 764 | } | ||
| 765 | } | ||
| 766 | |||
| 767 | // Regular screen rendering with current user context - use our custom ScreenTestImpl | ||
| 768 | def screenTest = new org.moqui.mcp.CustomScreenTestImpl(ec.ecfi) | ||
| 721 | .rootScreen(rootScreen) | 769 | .rootScreen(rootScreen) |
| 722 | .renderMode(renderMode ? renderMode : "mcp") | 770 | .renderMode(renderMode ? renderMode : "mcp") |
| 723 | .auth(ec.user.username) | 771 | .auth(ec.user.username) |
| ... | @@ -741,8 +789,27 @@ def startTime = System.currentTimeMillis() | ... | @@ -741,8 +789,27 @@ def startTime = System.currentTimeMillis() |
| 741 | 789 | ||
| 742 | def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 | 790 | def executionTime = (System.currentTimeMillis() - startTime) / 1000.0 |
| 743 | 791 | ||
| 744 | // Add screen HTML as main content | 792 | // Build result based on renderMode |
| 745 | def content = [] | 793 | def content = [] |
| 794 | if (renderMode == "mcp" && mcpData) { | ||
| 795 | // Return structured MCP data | ||
| 796 | def mcpResult = [ | ||
| 797 | screenPath: screenPath, | ||
| 798 | screenUrl: screenUrl, | ||
| 799 | executionTime: executionTime, | ||
| 800 | isError: isError | ||
| 801 | ] | ||
| 802 | if (mcpData.parameters) mcpResult.parameters = mcpData.parameters | ||
| 803 | if (mcpData.forms) mcpResult.forms = mcpData.forms | ||
| 804 | if (mcpData.actions) mcpResult.actions = mcpData.actions | ||
| 805 | if (output) mcpResult.htmlPreview = output.take(2000) + (output.length() > 2000 ? "..." : "") | ||
| 806 | |||
| 807 | content << [ | ||
| 808 | type: "text", | ||
| 809 | text: new groovy.json.JsonBuilder(mcpResult).toString() | ||
| 810 | ] | ||
| 811 | } else { | ||
| 812 | // Return raw output for other modes | ||
| 746 | content << [ | 813 | content << [ |
| 747 | type: "text", | 814 | type: "text", |
| 748 | text: output, | 815 | text: output, |
| ... | @@ -751,6 +818,7 @@ def startTime = System.currentTimeMillis() | ... | @@ -751,6 +818,7 @@ def startTime = System.currentTimeMillis() |
| 751 | executionTime: executionTime, | 818 | executionTime: executionTime, |
| 752 | isError: isError | 819 | isError: isError |
| 753 | ] | 820 | ] |
| 821 | } | ||
| 754 | 822 | ||
| 755 | result = [ | 823 | result = [ |
| 756 | content: content, | 824 | content: content, |
| ... | @@ -1130,10 +1198,10 @@ def startTime = System.currentTimeMillis() | ... | @@ -1130,10 +1198,10 @@ def startTime = System.currentTimeMillis() |
| 1130 | message: "Form parameters submitted", | 1198 | message: "Form parameters submitted", |
| 1131 | parametersProcessed: actionParams.keySet() | 1199 | parametersProcessed: actionParams.keySet() |
| 1132 | ] | 1200 | ] |
| 1133 | } else if (screenDef && screenDef.transitions) { | 1201 | } else if (screenDef && screenDef.hasTransitions()) { |
| 1134 | // Look for matching transition by name | 1202 | // Look for matching transition by name |
| 1135 | for (def transition : screenDef.transitions) { | 1203 | for (def transition : screenDef.getAllTransitions()) { |
| 1136 | if (transition.@name == action) { | 1204 | if (transition.name == action) { |
| 1137 | foundTransition = transition | 1205 | foundTransition = transition |
| 1138 | break | 1206 | break |
| 1139 | } | 1207 | } | ... | ... |
-
Please register or sign in to post a comment