UpdateServiceDefinition
Update or create an ABAP service definition: locks the object, updates source code, unlocks, and optionally activates. Requires service definition name and source code.
Instructions
Operation: Update, Create. Subject: ServiceDefinition. Will be useful for updating or creating service definition. Update source code of an existing ABAP service definition. Locks, updates, unlocks, and optionally activates.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| service_definition_name | Yes | Service definition name (e.g., ZSD_MY_SERVICE). Must exist in the system. | |
| source_code | Yes | Complete service definition source code. | |
| transport_request | No | Transport request number (e.g., E19K905635). Optional if object is local or already in transport. | |
| activate | No | Activate service definition after update. Default: true. |
Implementation Reference
- Main handler function for UpdateServiceDefinition tool. Locks the service definition, updates source code, checks it, unlocks it, optionally activates it, and parses activation warnings.
export async function handleUpdateServiceDefinition( context: HandlerContext, args: UpdateServiceDefinitionArgs, ) { const { connection, logger } = context; try { const { service_definition_name, source_code, transport_request, activate = true, } = args as UpdateServiceDefinitionArgs; // Validation if (!service_definition_name || !source_code) { return return_error( new Error('service_definition_name and source_code are required'), ); } // Get connection from session context (set by ProtocolHandler) // Connection is managed and cached per session, with proper token refresh via AuthBroker const serviceDefinitionName = service_definition_name.toUpperCase(); logger?.info( `Starting service definition source update: ${serviceDefinitionName}`, ); try { // Create client const client = createAdtClient(connection, logger); // Build operation chain: lock -> update -> check -> unlock -> (activate) // Note: No validation needed for update - service definition must already exist const shouldActivate = activate !== false; // Default to true if not specified // Lock let lockHandle: string | undefined; let activateResponse: any | undefined; try { lockHandle = await client .getServiceDefinition() .lock({ serviceDefinitionName }); // Update source code await client.getServiceDefinition().update( { serviceDefinitionName, sourceCode: source_code, transportRequest: args.transport_request, }, { lockHandle }, ); // Check try { await safeCheckOperation( () => client.getServiceDefinition().check({ serviceDefinitionName }), serviceDefinitionName, { debug: (message: string) => logger?.debug(`[UpdateServiceDefinition] ${message}`), }, ); } catch (checkError: any) { // If error was marked as "already checked", continue silently if (!(checkError as any).isAlreadyChecked) { // Real check error - rethrow throw checkError; } } } finally { if (lockHandle) { try { await client .getServiceDefinition() .unlock({ serviceDefinitionName }, lockHandle); logger?.info( `[UpdateServiceDefinition] Service definition unlocked: ${serviceDefinitionName}`, ); } catch (unlockError: any) { logger?.warn( `Failed to unlock service definition ${serviceDefinitionName}: ${unlockError?.message || unlockError}`, ); } } } // Wait for object to be ready after update (long polling) try { await client .getServiceDefinition() .read({ serviceDefinitionName }, 'inactive', { withLongPolling: true, }); } catch { // Continue anyway — activation will fail explicitly if object isn't ready } // Activate if requested if (shouldActivate) { const activateState = await client .getServiceDefinition() .activate({ serviceDefinitionName }); activateResponse = activateState.activateResult; } // Parse activation warnings if activation was performed let activationWarnings: string[] = []; if ( shouldActivate && activateResponse && typeof activateResponse.data === 'string' && activateResponse.data.includes('<chkl:messages') ) { const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@_', }); const result = parser.parse(activateResponse.data); const messages = result?.['chkl:messages']?.msg; if (messages) { const msgArray = Array.isArray(messages) ? messages : [messages]; activationWarnings = msgArray.map( (msg: any) => `${msg['@_type']}: ${msg.shortText?.txt || 'Unknown'}`, ); } } logger?.info( `✅ UpdateServiceDefinition completed successfully: ${serviceDefinitionName}`, ); // Return success result const stepsCompleted = ['lock', 'update', 'check', 'unlock']; if (shouldActivate) { stepsCompleted.push('activate'); } const result = { success: true, service_definition_name: serviceDefinitionName, transport_request: transport_request || 'local', activated: shouldActivate, message: shouldActivate ? `Service Definition ${serviceDefinitionName} updated and activated successfully` : `Service Definition ${serviceDefinitionName} updated successfully (not activated)`, uri: `/sap/bc/adt/ddic/srvd/sources/${encodeSapObjectName(serviceDefinitionName)}`, steps_completed: stepsCompleted, activation_warnings: activationWarnings.length > 0 ? activationWarnings : undefined, source_size_bytes: source_code.length, }; return return_response({ data: JSON.stringify(result, null, 2), status: 200, statusText: 'OK', headers: {}, config: {} as any, }); } catch (error: any) { logger?.error( `Error updating service definition source ${serviceDefinitionName}:`, error, ); const errorMessage = error.response?.data ? typeof error.response.data === 'string' ? error.response.data : JSON.stringify(error.response.data) : error.message || String(error); return return_error( new Error(`Failed to update service definition: ${errorMessage}`), ); } } catch (error: any) { return return_error(error); } } - Input schema and tool definition for UpdateServiceDefinition. Declares the tool name, available environments, description, and input schema with required fields: service_definition_name and source_code.
export const TOOL_DEFINITION = { name: 'UpdateServiceDefinition', available_in: ['onprem', 'cloud'] as const, description: 'Operation: Update, Create. Subject: ServiceDefinition. Will be useful for updating or creating service definition. Update source code of an existing ABAP service definition. Locks, updates, unlocks, and optionally activates.', inputSchema: { type: 'object', properties: { service_definition_name: { type: 'string', description: 'Service definition name (e.g., ZSD_MY_SERVICE). Must exist in the system.', }, source_code: { type: 'string', description: 'Complete service definition source code.', }, transport_request: { type: 'string', description: 'Transport request number (e.g., E19K905635). Optional if object is local or already in transport.', }, activate: { type: 'boolean', description: 'Activate service definition after update. Default: true.', }, }, required: ['service_definition_name', 'source_code'], }, } as const; - TypeScript interface for the UpdateServiceDefinition handler arguments.
interface UpdateServiceDefinitionArgs { service_definition_name: string; source_code: string; transport_request?: string; activate?: boolean; } - src/lib/handlers/groups/HighLevelHandlersGroup.ts:729-732 (registration)Registration of UpdateServiceDefinition in the HighLevelHandlersGroup, mapping its tool definition to the handler wrapped with context.
{ toolDefinition: UpdateServiceDefinition_Tool, handler: withContext(handleUpdateServiceDefinition), }, - src/handlers/compact/high/compactRouter.ts:143-144 (registration)Registration of handleUpdateServiceDefinition as the 'update' operation in the SERVICE_DEFINITION compact router.
update: handleUpdateServiceDefinition as unknown as CompactHandler, delete: handleDeleteServiceDefinition as unknown as CompactHandler,