docs: @Override
      public ResourceFactory createResourceFactory(Map<String, Object> props) throws Exception {
          final boolean trace = TraceComponent.isAnyTracingEnabled();
          if (trace && tc.isEntryEnabled())
              Tr.entry(tc, "createResourceFactory", props);
          //Place holder for admin object properties like queue/topic
          Hashtable<String, Object> adminObjectSvcProps = new Hashtable<String, Object>();
          //Store all the props from annotation as well as from deployment descriptor
          Map<String, Object> annotationDDProps = new HashMap<String, Object>();
  
          //Just move all the properties from props to annotationProps after resolving strings.
          VariableRegistry variableRegistry = variableRegistryRef.getServiceWithException();
          for (Map.Entry<String, Object> prop : props.entrySet()) {
              Object value = prop.getValue();
              if (value instanceof String)
                  value = variableRegistry.resolveString((String) value);
              annotationDDProps.put(prop.getKey(), value);
          }
  
          String application = (String) annotationDDProps.remove(AppDefinedResource.APPLICATION);
          String declaringApplication = (String) annotationDDProps.remove(DECLARING_APPLICATION);
          String module = (String) annotationDDProps.remove(AppDefinedResource.MODULE);
          String component = (String) annotationDDProps.remove(AppDefinedResource.COMPONENT);
          String jndiName = (String) annotationDDProps.remove(AdminObjectService.JNDI_NAME);
          annotationDDProps.remove(DESCRIPTION);
          annotationDDProps.remove(NAME);
  
          String adminObjectID = getadminObjectID(application, module, component, jndiName);
  
          StringBuilder filter = new StringBuilder(FilterUtils.createPropertyFilter(ID, adminObjectID));
          filter.insert(filter.length() - 1, '*');
          // Fail if server.xml is already using the id
          if (!removeExistingConfigurations(filter.toString()))
              throw new IllegalArgumentException(adminObjectID); // internal error, shouldn't ever have been permitted in server.xml
  
          adminObjectSvcProps.put(ID, adminObjectID);
          adminObjectSvcProps.put(CONFIG_DISPLAY_ID, adminObjectID);
          // Use the unique identifier because jndiName is not always unique for app-defined data sources
          adminObjectSvcProps.put(UNIQUE_JNDI_NAME, adminObjectID);
  
          adminObjectSvcProps.put(ResourceFactory.JNDI_NAME, jndiName);
          if (application != null) {
              adminObjectSvcProps.put(AppDefinedResource.APPLICATION, application);
              if (module != null) {
                  adminObjectSvcProps.put(AppDefinedResource.MODULE, module);
                  if (component != null)
                      adminObjectSvcProps.put(AppDefinedResource.COMPONENT, component);
              }
          }
          String resourceAdapter = ((String) annotationDDProps.remove(RESOURCE_ADAPTER));
          String destinationName = (String) annotationDDProps.get(JMSResourceDefinitionConstants.DESTINATION_NAME);
          String interfaceName = (String) annotationDDProps.remove(INTERFACE_NAME);
  
          //If the resource adapter type is wasJms, then the destination name has to be mapped with respective name in the resource adapter.
          if (JMSResourceDefinitionConstants.RESOURCE_ADAPTER_WASJMS.equals(resourceAdapter)) {
  
              // The destinationName specified by via annotation/dd has to be mapped to the respective adapter property.
              if (JMSResourceDefinitionConstants.JMS_QUEUE_INTERFACE.equals(interfaceName)) {
                  annotationDDProps.put(JMSResourceDefinitionConstants.JMS_QUEUE_NAME, destinationName);
              } else if (JMSResourceDefinitionConstants.JMS_TOPIC_INTERFACE.equals(interfaceName)) {
                  annotationDDProps.put(JMSResourceDefinitionConstants.JMS_TOPIC_NAME, destinationName);
              }
              //If the resource adapter type is wmqJms, then the destination name has to be mapped with respective name in the resource adapter.
          } else if (JMSResourceDefinitionConstants.RESOURCE_ADAPTER_WMQJMS.equals(resourceAdapter)) {
  
              // The destinationName specified by via annotation/dd has to be mapped to the respective adapter property.
              if (JMSResourceDefinitionConstants.JMS_QUEUE_INTERFACE.equals(interfaceName)) {
                  annotationDDProps.put(JMSResourceDefinitionConstants.WMQ_QUEUE_NAME, destinationName);
              } else if (JMSResourceDefinitionConstants.JMS_TOPIC_INTERFACE.equals(interfaceName)) {
                  annotationDDProps.put(JMSResourceDefinitionConstants.WMQ_TOPIC_NAME, destinationName);
              }
          }
          //Get props with default values only and see if the same is specified by the user in annotation/dd, then use that value otherwise set the default value.
          //Note: Its not necessary for the user to specify the props which has default value, so we set them in here.  
          Dictionary<String, Object> adminObjectDefaultProps = getDefaultProperties(resourceAdapter, interfaceName);
  
          for (Enumeration<String> keys = adminObjectDefaultProps.keys(); keys.hasMoreElements();)
          {
              String key = keys.nextElement();
              Object value = adminObjectDefaultProps.get(key);
  
              //Override the administered object default property values with values provided annotation
              if (annotationDDProps.containsKey(key))
                  value = annotationDDProps.remove(key);
  
              if (value instanceof String)
                  value = variableRegistry.resolveString((String) value);
  
              adminObjectSvcProps.put(JMSResourceDefinitionConstants.PROPERTIES_REF_KEY + key, value);
          }
  
          //Get all the properties for a given resource(get the resource by the interfaceName) from the corresponding resource adapter, 
          //then see if user specified any of these props in annotation/dd, if yes set that value otherwise ignore.
          //Note: The above section for handling default values can be eliminated by handling the same here in this section since we get all the properties. Will be taken care in future.
          AttributeDefinition[] ads = getAttributeDefinitions(resourceAdapter, interfaceName);
          for (AttributeDefinition attributeDefinition : ads) {
              Object value = annotationDDProps.remove(attributeDefinition.getID());
              if (value != null) {
  
                  if (value instanceof String)
                      value = variableRegistry.resolveString((String) value);
  
                  adminObjectSvcProps.put(JMSResourceDefinitionConstants.PROPERTIES_REF_KEY + attributeDefinition.getID(), value);
              }
          }
  
          adminObjectSvcProps.put(BOOTSTRAP_CONTEXT, "(id=" + resourceAdapter + ")");
  
          BundleContext bundleContext = FrameworkUtil.getBundle(AdminObjectService.class).getBundleContext();
  
          StringBuilder adminObjectFilter = new StringBuilder(200);
          adminObjectFilter.append("(&").append(FilterUtils.createPropertyFilter(ID, adminObjectID));
          adminObjectFilter.append(FilterUtils.createPropertyFilter(Constants.OBJECTCLASS, AdminObjectService.class.getName())).append(")");
  
          ResourceFactory factory = new AppDefinedResourceFactory(this, bundleContext, adminObjectID, adminObjectFilter.toString(), declaringApplication);
          try {
  
              String bundleLocation = bundleContext.getBundle().getLocation();
              ConfigurationAdmin configAdmin = configAdminRef.getService();
  
              Configuration adminObjectSvcConfig = configAdmin.createFactoryConfiguration(AdminObjectService.ADMIN_OBJECT_PID, bundleLocation);
              adminObjectSvcConfig.update(adminObjectSvcProps);
          } catch (Exception x) {
              factory.destroy();
              throw x;
          } catch (Error x) {
              factory.destroy();
              throw x;
          }
  
          if (trace && tc.isEntryEnabled())
              Tr.exit(tc, "createResourceFactory", factory);
          return factory;
      }