docs: @FFDCIgnore(value = { NumberFormatException.class, Throwable.class })
      private ResourceAdapter configureResourceAdapter() throws Exception {
          final boolean trace = TraceComponent.isAnyTracingEnabled();
  
          String resourceAdapterClassName = (String) properties.get(RESOURCE_ADAPTER_CLASS);
          if (resourceAdapterClassName == null)
              return null;
          ResourceAdapter instance = (ResourceAdapter) loadClass(resourceAdapterClassName).newInstance();
  
          // Assume all configured properties are invalid until we find them
          Set<String> invalidPropNames = new HashSet<String>();
          for (Enumeration<String> names = properties.keys(); names.hasMoreElements();) {
              String name = names.nextElement();
              if (!INTERNAL_PROPS.contains(name) && !Constants.OBJECTCLASS.equals(name) && name.indexOf('.') < 0 && name.indexOf('-') < 0 && !name.endsWith("Ref"))
                  invalidPropNames.add(name);
          }
  
          Class<?> objectClass = instance.getClass();
          for (PropertyDescriptor descriptor : Introspector.getBeanInfo(objectClass).getPropertyDescriptors()) {
              String name = MetatypeGenerator.toCamelCase(descriptor.getName());
              Object value = properties.get(name);
              propertyDescriptors.put(name, descriptor);
  
              if (value != null)
                  try {
                      invalidPropNames.remove(name);
  
                      boolean isProtectedString = value instanceof SerializableProtectedString;
                      if (isProtectedString)
                          value = new String(((SerializableProtectedString) value).getChars());
                      if (value instanceof String && name.toUpperCase().indexOf("PASSWORD") >= 0) {
                          value = PasswordUtil.getCryptoAlgorithm((String) value) == null ? value : PasswordUtil.decode((String) value);
                          isProtectedString = true;
                      }
                      if (trace && tc.isDebugEnabled())
                          Tr.debug(tc, "set " + name + '=' + (isProtectedString ? "***" : value));
  
                      Class<?> type = descriptor.getPropertyType();
                      Method writeMethod = descriptor.getWriteMethod();
  
                      // Some ra.xml files specify everything as String even when that's not true. If so, try to convert it:
                      if (value instanceof String) {
                          if (!type.isAssignableFrom(value.getClass()))
                              try {
                                  value = Utils.convert((String) value, type);
                              } catch (NumberFormatException numFormatX) {
                                  // If the property type can't be converted to what the bean info wants,
                                  // then go looking for a matching method of the proper type (that isn't on the bean info).
                                  try {
                                      writeMethod = objectClass.getMethod(writeMethod.getName(), String.class);
                                  } catch (NoSuchMethodException x) {
                                      throw numFormatX;
                                  }
                              }
                      }
                      // Allow the metatype to use primitive types instead of String, in which case we can easily convert to String:
                      else if (String.class.equals(type))
                          value = value.toString();
                      // When ibm:type="duration" is used, we always get Long. If necessary, convert to another numeric type:
                      else if (value instanceof Number && !type.isAssignableFrom(value.getClass()))
                          value = Utils.convert((Number) value, type);
  
                      writeMethod.invoke(instance, value);
                  } catch (Throwable x) {
                      x = x instanceof InvocationTargetException ? x.getCause() : x;
                      x = Utils.ignoreWarnOrFail(tc, x, x.getClass(), "J2CA8500.config.prop.error", name, getConfigElementName(), objectClass.getName(), x);
                      if (x != null) {
                          InvalidPropertyException propX = new InvalidPropertyException(name, x);
                          propX.setInvalidPropertyDescriptors(new PropertyDescriptor[] { descriptor });
                          FFDCFilter.processException(propX, getClass().getName(), "239");
                          throw propX;
                      }
                  }
          }
  
          // Invalid properties
          for (String name : invalidPropNames) {
              InvalidPropertyException x = Utils.ignoreWarnOrFail(tc, null, InvalidPropertyException.class, "J2CA8501.config.prop.unknown",
                                                                  name, getConfigElementName(), objectClass.getName());
              if (x != null) {
                  FFDCFilter.processException(x, Utils.class.getName(), "249");
                  throw x;
              }
          }
          if (bvalHelper != null) {
              ResourceAdapterMetaData raMetaData = resourceAdapterSvc.getResourceAdapterMetaData();
              if (raMetaData != null) {
                  bvalHelper.validateInstance(raMetaData.getModuleMetaData(), resourceAdapterSvc.getClassLoader(), instance);
              }
          }
          return instance;
      }