IdentityIQ Connector-classloader FAQ
- Why Use the Connector-classloader?
- Solve the Long-term Problem
- High-level Understanding of the Connector-classloader Design
- Common Problems and Solutions
- Use of Third-party Libraries in Customizations, Not Available OOTB
- Conflicting Libraries With System-classloader
- Instantiating Connectors Without Using ConnectorFactory in the Customization
- Using the Connector’s Concrete Methods in the Customization Rule
- Custom Connector Development Guide
Why Use the Connector-classloader?
- Enables third-party library upgrades, changes for custom connectors, and connector customization rules
- You have two different version of the same connectors that need different libraries
- There is a third-party library conflict between two connectors
- Security and licensing obligations
Solve the Long-term Problem
SailPoint connectors are continuously being upgraded with new features and security fixes. Changes to libraries and code are inevitable. The connector-classloader and library isolation projects are a step towards fixing the problems of customization that can happen during upgrades.
The following connector-classloader features help reduce the customization failures during upgrades:
- Facilitates customization, rules, and custom connectors to add or use their own libraries. Customization becomes independent from the OOTB libraries and remains unaffected due to any upgrades or changes in the connector libraries.
- Enforces better practices in customization so that connector level changes do no affect customization.
High-level Understanding of the Connector-classloader Design
-
Class loading is driven by the sequence of paths/locations or jars available in the classpath. On the request to load the class, the classloader traverses the classpath items one by one to search the class. It returns the class from the first occurrence and stops searching.
The following is the typical classpath for the connector-classloader. This gives you an idea of how, and from where, the classes for connectors are loaded. It also provides insight into the priority for classpath.- Appconfig, if specified in the application.xml:
<!-- IdentityIQ filePathPrefix = Directory Path including /WEB-INF --> <entry key="connector-classpath"> <value> <List> <String>\lib-connectors\JDBCCustom\commons-codec-1.9.jar</String> <!-- path of single jar --> <String>\lib-connectors\ JDBCCustom \</String> <!-- path of folder, all jars under the folder will be added to classpath --> </List> </value> </entry>
- ConnectorBundle jar in which the Connector class is packed
- IdentityIQ WEB-INF/lib
- Appconfig, if specified in the application.xml:
- The connector-classloader is used to load the connector and its libraries only if the connector is instantiated using ConnectorFactory, as provided below:
ConnectorFactory.getConnector(application, instance)
- If any rule is triggered from the connector operation (for example, beforeRule or afterRule), the connector-classloader is used as context classloader BeanShell code execution. Therefore, all libraries available to a connector are also available to BeanShell code during execution.
- For more information about configurations available through the connector-classloader, see https://community.sailpoint.com/t5/other-Documents/Connector-Classloader/ta-p/157873.
Common Problems and Solutions
Use of Third-party Libraries in Customizations, Not Available OOTB
Before starting, ensure that all third-party libraries used:
- Are from an authentic/trusted source.
- Do not incur legal obligations.
- Are free from known security vulnerabilities.
- Are compatible with the supported JDK versions of IdentityIQ.
Never add the following libraries explicitly to the classpath of any application, as they can cause class loading or conflict errors (these libraries are infrastructure libraries provided OOTB and are shared across IdentityIQ):
- Openconnector framework classes or jar: Responsible for providing connector infrastructure like interfaces and functionality control.
- Any OOTB connector bundle jar.
- Aspect*.jar: Responsible for providing the aspect infrastructure.
- Commons-logging*.jar, log4j-*.jar, slf4j-api*.jar: Responsible for providing logging infrastructure.
- Bsf*.jar and bsh*.jar: Used to execute Rules.
To enable third-party libraries, complete the following:
- Create a subfolder in the WEB-INF/lib-connectors folder. For example, WEB-INF/lib-connectors/XYZcustom
- Save a copy of the required third-party libraries for the customization.
- In the Application Definition for your application that is using this customization, add a connector-classpath entry to the Attributes map. This entry can point to the jars individually or to the folder, as shown in the example below. This adds the specified jar file, or all jars in the folder, to the classpath for the connector.
<!-- IIQ filePathPrefix = Directory Path including /WEB-INF -->
<entry key="connector-classpath">
<value>
<List>
<String>\lib-connectors\JDBCCustom\commons-codec-1.9.jar</String> <!-- path of single jar -->
<String>\lib-connectors\ JDBCCustom\</String> <!-- path of folder, all jars under the folder will be added to classpath -->
</List>
</value>
</entry>
Conflicting Libraries With System-classloader
Sometimes libraries have a conflict with the system-classloader, as the same library gets loaded by both the customization and the system-classloader. This can cause some problems. For example you could see the following: java.lang.LinkageError: loader constraint violation:, ClassCastException, or cannot be cast to: For reference, see https://sailpoint.atlassian.net/browse/CONJUBILEE-1467.
To solve these issues, you can delegate the classloading for the specific libraries, jar, or classes to the system-classloader by using the following configuration:
<entry key="load-by-sysclassloader">
<value>
<List>
<String>velocity.jar</String>
<String>org.apache.velocity</String> <!-- package to delegate, Connector Classloader will delegate all the classes under this package to sysclassloader to load –->
<String>org.apache.bsf.engines.jacl.BSFCommand.class</String> <!-- Class to delegate, Connector Classloader will delegate the specified classes to sysclassloader to load -->
</List>
</value>
</entry>
Instantiating Connectors Without Using ConnectorFactory in the Customization
The correct way to instantiate a connector in your implementation-specific code is:
Connector connector = ConnectorFactory.getConnector(application, null);
As mentioned in the seconf bullet of the high-level understanding of the design, the connector-classloader is associated with the connector only when you instantiate with ConnectorFactory. Otherwise, it leads to exceptions of ClassNotFoundException or NoClassDefFoundError.
Using the Connector’s Concrete Methods in the Customization Rule
If you are using any of the concrete methods from the connector as a utility or for some other purpose, SailPoint recommends using the concrete methods as connectors are continuously being upgraded. It is inevitable that a few methods or classes will be moved, updated, or dropped during this process. So, you should not use any connector methods other than the connector interface contract. As seen in the following example:
Connector connector = ConnectorFactory.getConnector(application, null);
connector.provision(provisioningPlan);
connector.getObject("group", identity, options);
Custom Connector Development Guide
For more information on custom connector development, see the following guides: