public <T> T submitRequest(String pluginId, String requestName, PluginInteractionCallback<T> pluginInteractionCallback) {
        if (!pluginManager.isPluginOfType(extensionName, pluginId)) {
            throw new RecordNotFoundException(format("Did not find '%s' plugin with id '%s'. Looks like plugin is missing", extensionName, pluginId));
        }
        try {
            String resolvedExtensionVersion = pluginManager.resolveExtensionVersion(pluginId, extensionName, goSupportedVersions);
            DefaultGoPluginApiRequest apiRequest = new DefaultGoPluginApiRequest(extensionName, resolvedExtensionVersion, requestName);
            apiRequest.setRequestBody(pluginInteractionCallback.requestBody(resolvedExtensionVersion));
            apiRequest.setRequestParams(pluginInteractionCallback.requestParams(resolvedExtensionVersion));
            apiRequest.setRequestHeaders(pluginInteractionCallback.requestHeaders(resolvedExtensionVersion));
            GoPluginApiResponse response = pluginManager.submitTo(pluginId, extensionName, apiRequest);
            if (response == null) {
                throw new RuntimeException("The plugin sent a null response");
            }
            if (DefaultGoApiResponse.SUCCESS_RESPONSE_CODE == response.responseCode()) {
                return pluginInteractionCallback.onSuccess(response.responseBody(), response.responseHeaders(), resolvedExtensionVersion);
            }
            pluginInteractionCallback.onFailure(response.responseCode(), response.responseBody(), resolvedExtensionVersion);

            throw new RuntimeException(format("The plugin sent a response that could not be understood by Go. Plugin returned with code '%s' and the following response: '%s'", response.responseCode(), response.responseBody()));
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(format("Interaction with plugin with id '%s' implementing '%s' extension failed while requesting for '%s'. Reason: [%s]", pluginId, extensionName, requestName, e.getMessage()), e);
        }
    }
@Test
    void shouldNotInvokeSuccessBlockOnFailureResponse() {
        when(response.responseCode()).thenReturn(DefaultGoApiResponse.INTERNAL_ERROR);
        when(response.responseBody()).thenReturn("junk");
        when(pluginManager.submitTo(eq(pluginId), eq(extensionName), any(GoPluginApiRequest.class))).thenReturn(response);
        try {
            helper.submitRequest(pluginId, requestName, new DefaultPluginInteractionCallback<>() {
                @Override
                public Object onSuccess(String responseBody, Map<String, String> responseHeaders, String resolvedExtensionVersion) {
                    isSuccessInvoked[0] = true;
                    return null;
                }
            });
            fail("should throw exception");
        } catch (Exception e) {
            assertThat(e.getMessage()).isEqualTo("The plugin sent a response that could not be understood by Go. Plugin returned with code '500' and the following response: 'junk'");
            assertThat(isSuccessInvoked[0]).isFalse();
            verify(pluginManager).submitTo(eq(pluginId), eq(extensionName), any(GoPluginApiRequest.class));
        }
    }