@Override
  protected ServerServiceDesc createServiceDesc(ServiceId id) throws ServiceException {
    ServerServiceId serverSvcId = (ServerServiceId) id;
    String adminName = id.getAdminName();
    ServiceConfigHolder config = ServiceConfigManager.getInstance().getConfig(adminName);
    QName serviceQName = config.getServiceQName();

    ClassLoader cl = Thread.currentThread().getContextClassLoader();

    MessageProcessorConfigHolder processorConfig = config.getMessageProcessorConfig();
    TypeMappingConfigHolder typeMappingsCfg = config.getTypeMappings();

    Pipeline requestPipeline = createPipeline(id, PipelineMode.REQUEST, processorConfig, cl);
    Pipeline responsePipeline = createPipeline(id, PipelineMode.RESPONSE, processorConfig, cl);

    Class serviceInterfaceClass = loadServiceInterfaceClass(config, true, cl);

    ServiceTypeMappings typeMappings =
        createTypeMappings(id, typeMappingsCfg, serviceInterfaceClass, cl);

    Collection<String> unsupportedOperations = config.getUnsupportedOperation();
    Map<String, ServiceOperationDesc> operations =
        createOperations(
            id,
            typeMappingsCfg,
            unsupportedOperations,
            typeMappings,
            serviceQName,
            cl,
            config.getOperationProperties());
    RequestPatternMatcher<ServiceOperationDesc> operationMatcher =
        createOperationsMatcher(operations.values());

    Map<String, ProtocolProcessorDesc> protocols =
        createProtocolProcessors(serverSvcId, processorConfig.getProtocolProcessors(), cl);
    RequestPatternMatcher<ProtocolProcessorDesc> protocolMatcher =
        createProtocolProcessorsMatcher(processorConfig.getProtocolProcessors(), protocols);

    Collection<String> supportedDataBindings = config.getSupportedDataBindings();
    Set<Class> rootClasses = getRootClassesFromOperations(operations.values());
    for (String className : typeMappingsCfg.getJavaTypes()) {
      Class clazz = ReflectionUtils.loadClass(className, null, true, cl);
      if (clazz == null) {
        if (LOGGER.isLogEnabled(LogLevel.WARN)) {
          LOGGER.log(LogLevel.WARN, "Unable to load type mapping class: " + className);
        }
      } else {
        rootClasses.add(clazz);
      }
    }
    Map<String, DataBindingDesc> bindings =
        createDataBindings(
            serverSvcId, processorConfig, supportedDataBindings, rootClasses, true, cl, true);

    DataBindingDesc defaultRequestBinding =
        getDefaultRequestDataBinding(config, supportedDataBindings, bindings, adminName);
    DataBindingDesc defaultResponseBinding =
        getDefaultResponseDataBinding(config, supportedDataBindings, bindings, adminName);

    RequestPatternMatcher<DataBindingDesc> bindingMatcherForRequest =
        new RequestPatternMatcher<DataBindingDesc>(true);
    RequestPatternMatcher<DataBindingDesc> bindingMatcherForResponse =
        new RequestPatternMatcher<DataBindingDesc>(true);
    createDataBindingsMatchers(
        bindings.values(), bindingMatcherForRequest, bindingMatcherForResponse);

    ErrorMapper errorMapper = createErrorMapper(processorConfig, serverSvcId, cl);
    ErrorDataProvider errorDataProviderClass = getErrorDataProviderClass(processorConfig, cl);
    List<LoggingHandler> loggingHandlers = createLoggingHandlers(id, processorConfig, cl);

    String serviceDispatcherClassName = getDispatcherClassName(config);

    String serviceImplClassName = config.getServiceImplClassName();
    String implFactory = config.getServiceImplFactoryClassName();

    BaseServiceRequestDispatcher<?> serviceDispatcher = null;
    try {
      serviceDispatcher =
          ReflectionUtils.createInstance(
              serviceDispatcherClassName, BaseServiceRequestDispatcher.class, cl);
    } catch (ServiceException se) {
      String mode = "Service Impl";
      if (implFactory != null) {
        mode += " factory";
      }
      throw new ServiceCreationException(
          ErrorDataFactory.createErrorData(
              ErrorConstants.SVC_FACTORY_MISSING_DISPATCHER_IMPL,
              ErrorConstants.ERRORDOMAIN,
              new Object[] {serviceDispatcherClassName}),
          se.getCause());
    }

    VersionCheckHandler versionCheckHandler = createVersionCheckHandler(serverSvcId, config, cl);

    serviceDispatcher.init(
        serverSvcId,
        serviceInterfaceClass,
        serviceImplClassName,
        cl,
        operations.values(),
        versionCheckHandler,
        implFactory,
        config.isImplCached());

    Dispatcher requestDispatcher = new SimpleInvokerDispatcher(serviceDispatcher);
    Dispatcher responseDispatcher = new SimpleServerResponseDispatcher(true);

    Collection<GlobalIdEntry> registryEntries =
        GlobalRegistryConfigManager.getInstance().getAllEntries();
    Map<String, GlobalIdDesc> globalIdMap = createGlobalIdMap(registryEntries, config);

    Charset serviceCharset = null; // default is to use request charset
    String serviceCharsetName = config.getDefaultEncoding();
    if (serviceCharsetName != null) {
      try {
        serviceCharset = Charset.forName(serviceCharsetName);
      } catch (Exception e) {
        throw new ServiceException(
            ErrorDataFactory.createErrorData(
                ErrorConstants.SVC_FACTORY_UNSUPPORTED_CHARSET,
                ErrorConstants.ERRORDOMAIN,
                new Object[] {serviceCharsetName, adminName}),
            e);
      }
    }

    UrlMappingsDesc urlMappings = loadUrlMappings(adminName, config);
    OperationMappings operationMappings = config.getOperationMappings();
    if (operationMappings == null) {
      operationMappings = new OperationMappings();
    }
    HeaderMappingsDesc requestHeaderMappings =
        loadHeaderMappings(adminName, config.getRequestHeaderMappingOptions(), true);
    HeaderMappingsDesc responseHeaderMappings =
        loadHeaderMappings(adminName, config.getResponseHeaderMappingOptions(), false);

    SecurityPolicyConfigHolder securityPolicy = config.getSecurityPolicy();
    Map<String, Map<String, String>> authentOperationsMap =
        new HashMap<String, Map<String, String>>();
    loadSecurityPolicy(adminName, securityPolicy, operations, authentOperationsMap);

    CachePolicyDesc cachePolicyDesc = null;
    if (config.getCachePolicy() != null) {
      cachePolicyDesc =
          CachePolicyDesc.create(config.getCachePolicy(), createOpRequestTypeDesc(operations));
    }

    List<String> serviceLayers =
        ServiceConfigManager.getInstance().getGlobalConfig().getServiceLayerNames();

    String httpErrorMapperClassName = config.getHttpErrorMapper();
    HttpErrorMapper httpErrorMapper = null;
    if (httpErrorMapperClassName != null) {
      httpErrorMapper =
          ReflectionUtils.createInstance(httpErrorMapperClassName, HttpErrorMapper.class, cl);
    }

    ServerServiceDesc result =
        new ServerServiceDesc(
            serverSvcId,
            serviceQName,
            config,
            requestPipeline,
            responsePipeline,
            requestDispatcher,
            responseDispatcher,
            operations,
            protocols,
            bindings,
            typeMappings,
            cl,
            loggingHandlers,
            serviceInterfaceClass,
            operationMatcher,
            protocolMatcher,
            bindingMatcherForRequest,
            bindingMatcherForResponse,
            serviceImplClassName,
            errorMapper,
            errorDataProviderClass,
            globalIdMap,
            versionCheckHandler,
            serviceCharset,
            urlMappings,
            operationMappings,
            requestHeaderMappings,
            responseHeaderMappings,
            authentOperationsMap,
            defaultRequestBinding,
            defaultResponseBinding,
            serviceLayers,
            cachePolicyDesc,
            config.getRequestParamsDescriptor(),
            implFactory,
            httpErrorMapper);

    return result;
  }