Creating and Configuring Java Extensions for SOAP driver

Hi,

Im reading the documentation for adding a java extension to the SOAP driver i need to develop.

In the documentation about java extensions its mentioned that I can use some samplecode.

The documentation says "Using the sample code and SOAP Driver Javadoc found at the NetIQ Developer Downloads Web site as a guide, write the Java code for your class"

The link for "NetIQ Developer Downloads Web site" takes me here https://www.novell.com/documentation/dirxmldrivers/javadoc/api/

But I dont see where i can find any samplecode.

Anyone have any idea where it may be found?

  • 0  

    You're very right, difficult to find, the SDK is here: https://www.netiq.com/documentation/identity-manager-developer/driver-developer-kit.html - but the SDK does not contain any example code for the extension classes for the SOAP (or REST) driver.

    You can also look in SOAPUtil.jar which has the classes - no code though.

    If you ever find the example code please share the link.

  • Verified Answer

    +1  

    They keep moving stuff around, sometimes with working re-directs from well known old paths.  But then they move the site a second, and third, and fourth time and the redirects get lost.  I have hundreds (450+) articles on this site and they have broken the redirects so many times I have lost some ofthem...

    Anyway, you want this:

    https://www.netiq.com/documentation/identity-manager-developer/driver-developer-kit.html

    Get the Winders or Linux kit ya, from 2018 but really not been updated much.  Not much changed in this aspect.

    The Extensions class is sort of what you need but there is a different skeleton that you really need that I do not see in there.  Ithas the 4 access points the SOAP and JDBC drivers have.  I may have to find my copy and post it here instead.

  • Suggested Answer

    0   in reply to   

    Here's the sample code. 

    ByteArrayModifiers

    /*
     * Copyright (c) 2005 Novell, Inc. All Rights Reserved.
     *
     * Novell hereby grants You a royalty-free, non-exclusive license to use this Novell sample code in extending the
     * applicable Novell product.
     *
     * THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
     * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
     */
    
    package com.novell.nds.dirxml.driver.soap.examples;
    
    import com.novell.nds.dirxml.driver.soap.util.ByteArrayModifiers;
    import com.novell.nds.dirxml.driver.soap.util.Tracer;
    import java.util.Properties;
    
    public class ByteArrayModifiersExample implements ByteArrayModifiers {
        private Tracer tracer = null;
    
        /**
         * The init method is called by the driver when this class is first instantiated. This method will only be called
         * once.
         * @param parameterString
         * @param tracer An instance of an object implementing the Tracer interface. Use the trace method of this object
         *               to send messages to DSTrace.
         * @return       A Properties object for communicating with the driver shim. The only property defined at this time
         *               is "secure" which indicates whether or not this extension transports or stores data in the clear.
         * @see com.novell.nds.dirxml.driver.soap.util.Extension#init(String, Tracer)
         */
        public Properties init(String parameterString, Tracer tracer) {
            this.tracer = tracer;
            tracer.trace("DocumentModifiersExample.init() init string; " + parameterString);
            // Process the parameterString here. You can control what is in the parameterString by setting the appropriate
            // "Init Parameter" setting in the configuration. See the driver documentation for more details.
    
            // Before the init method returns, we must create a Properties object that contains the properties defined for
            // communicating with the driver shim. So far, only "secure" has been defined and should have the value "false"
            // if this extension will transport or store data insecurely. If you are only examining or modifying data within
            // this extension, then use the value "true".
            Properties properties = new Properties();
            properties.put("secure", "true");
            return properties;
        }
    
        /**
         * Used to access (and modify if desired) the data received from the engine as a
         * subscriber command before it is sent to the application. This method is called
         * after operation-data has been removed from the data (if it was present).
         * @param data the byte array received from the engine as a subscriber command.
         * @return a byte array that will be sent to the application as an HTTP request.
         * @see ByteArrayModifiers#modifySubscriberRequest(byte[])
         */
        public byte[] modifySubscriberRequest(byte[] data) {
            tracer.trace("ByteArrayModifiersExample.modifySubscriberRequest()");
    
            // Read and, if necessary, modify the subscriber request here. Otherwise, just return the same array.
    
            return data;
        }
    
        /**
         * Used to access (and modify if desired) the data received from the application as the
         * result to a subscriber command before it is sent to the engine. This method is called
         * before operation-data is restored to the data (if it was present on the request).
         * Note: If the data received from the application is not XML, this method MUST convert it
         * into valid XML.
         * @param data the HTTP response received from the application as the result of a
         *             subscriber command.
         * @return a byte array that will be converted to XML and sent to the engine as the result
         *         of a subscriber command.
         * @see ByteArrayModifiers#modifySubscriberResponse(byte[])
         */
        public byte[] modifySubscriberResponse(byte[] data) {
            tracer.trace("ByteArrayModifiersExample.modifySubscriberResponse()");
    
            // Read and, if necessary, modify the subscriber response here. Otherwise, just return the same array.
    
            return data;
        }
    
        /**
         * Used to access (and modify if desired) the data received from the application as a
         * publisher event before it is sent to the engine. Note: If the data received from the
         * application is not XML, this method MUST convert it into valid XML.
         * @param data the HTTP request received from the application as a publisher event.
         * @return a byte array that will be converted to XML and sent to the engine as a publisher event.
         * @see ByteArrayModifiers#modifyPublisherRequest(byte[])
         */
        public byte[] modifyPublisherRequest(byte[] data) {
            tracer.trace("ByteArrayModifiersExample.modifyPublisherRequest()");
    
            // Read and, if necessary, modify the publisher request here. Otherwise, just return the same array.
    
            return data;
        }
    
        /**
         * Used to access (and modify if desired) the data received from the engine in
         * response to a publisher event before it is sent to the application.
         * @param data the byte array received from the engine as response to a publisher event.
         * @return a byte array that will be sent to the application as an HTTP response.
         * @see ByteArrayModifiers#modifyPublisherResponse(byte[])
         */
        public byte[] modifyPublisherResponse(byte[] data) {
            tracer.trace("ByteArrayModifiersExample.modifyPublisherResponse()");
    
            // Read and, if necessary, modify the publisher response here. Otherwise, just return the same array.
    
            return data;
        }
    }
    

    DocumentModifiers
    /*
     * Copyright (c) 2005 Novell, Inc. All Rights Reserved.
     *
     * Novell hereby grants You a royalty-free, non-exclusive license to use this Novell sample code in extending the
     * applicable Novell product.
     *
     * THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
     * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
     */
    
    package com.novell.nds.dirxml.driver.soap.examples;
    
    import org.w3c.dom.Document;
    import java.util.Properties;
    import com.novell.nds.dirxml.driver.soap.util.DocumentModifiers;
    import com.novell.nds.dirxml.driver.soap.util.Tracer;
    
    public class DocumentModfiersExample implements DocumentModifiers {
        Tracer tracer = null;
    
        /**
         * The init method is called by the driver when this class is first instantiated. This method will only be called
         * once.
         * @param parameterString
         * @param tracer An instance of an object implementing the Tracer interface.
         *               Use the trace method of this object to send messages to DSTrace.
         * @return       A Properties object for communicating with the driver shim. The only property defined at this time
         *               is "secure" which indicates whether or not this extension transports or stores data in the clear.
         * @see com.novell.nds.dirxml.driver.soap.util.Extension#init(String, Tracer)
         */
        public Properties init(String parameterString, Tracer tracer) {
            this.tracer = tracer;
            tracer.trace("DocumentModifiersExample.init() init string; " + parameterString);
            // Process the parameterString here. You can control what is in the parameterString by setting the appropriate
            // "Init Parameter" setting in the configuration. See the driver documentation for more details.
    
            // Before the init method returns, we must create a Properties object that contains the properties defined for
            // communicating with the driver shim. So far, only "secure" has been defined and should have the value "false"
            // if this extension will transport or store data insecurely. If you are only examining or modifying data within
            // this extension, then use the value "true".
            Properties properties = new Properties();
            properties.put("secure", "true");
            return properties;
        }
    
        /**
         * Used to access (and modify if desired) the DOM document received from the
         * engine as a subscriber command before it is sent to the application. This
         * method is called before operation-data is removed from the document (if 
         * it was present).
         * @param document the Document received from the engine as a subscriber command.
         * @return the same Document passed into this method (may be modified if desired)
         * @see DocumentModifiers#modifySubscriberRequest(Document)
         */
        public Document modifySubscriberRequest(Document document) {
            tracer.trace("DocumentModifiersExample.modifySubscriberRequest()");
            // This is where you can access (and modify if desired) the document.
            // You are expected to return a valid document. If you need to make
            // changes, don't create a new document. Just make the changes within
            // the existing document then return that. If you don't need to
            // modify it, just return the same document you are passed unchanged.
            return document;
        }
    
        /**
         * Used to access (and modify if desired) the DOM document received by the
         * application as a response to a subscriber command before it is sent to
         * the engine. If operation-data was present on the request, it has been
         * restored again before the method is called.
         * @param document the Document received from the application as a response to
         *                 a subscriber command.
         * @return the same Document passed into this method (may be modified if desired)
         * @see DocumentModifiers#modifySubscriberResponse(Document)
         */
        public Document modifySubscriberResponse(Document document) {
            tracer.trace("DocumentModifiersExample.modifySubscriberResponse()");
            // This is where you can access (and modify if desired) the document.
            // You are expected to return a valid document. If you need to make
            // changes, don't create a new document. Just make the changes within
            // the existing document then return that. If you don't need to
            // modify it, just return the same document you are passed unchanged.
            return document;
        }
    
        /**
         * Used to access (and modify if desired) the DOM document received by the
         * application as a publisher event before it is sent to the engine.
         * @param document the Document received from the application as a publisher
         *                 event.
         * @return the same Document passed into this method (may be modified if desired)
         * @see DocumentModifiers#modifyPublisherRequest(Document)
         */
        public Document modifyPublisherRequest(Document document) {
            tracer.trace("DocumentModifiersExample.modifyPublisherRequest()");
            // This is where you can access (and modify if desired) the document.
            // You are expected to return a valid document. If you need to make
            // changes, don't create a new document. Just make the changes within
            // the existing document then return that. If you don't need to
            // modify it, just return the same document you are passed unchanged.
            return document;
        }
    
        /**
         * Used to access (and modify if desired) the DOM document received as a response
         * from the engine to a publisher event before it is sent to the application.
         * @param document the Document received by the engine as the result of a
         *                 publisher event.
         * @return the same Document passed into this method (may be modified if desired)
         * @see DocumentModifiers#modifyPublisherResponse(Document)
         */
        public Document modifyPublisherResponse(Document document) {
            tracer.trace("DocumentModifiersExample.modifyPublisherResponse()");
            // This is where you can access (and modify if desired) the document.
            // You are expected to return a valid document. If you need to make
            // changes, don't create a new document. Just make the changes within
            // the existing document then return that. If you don't need to
            // modify it, just return the same document you are passed unchanged.
            return document;
        }
    }
    
    SchemaReporter
    /*
     * Copyright (c) 2005 Novell, Inc. All Rights Reserved.
     *
     * Novell hereby grants You a royalty-free, non-exclusive license to use this Novell sample code in extending the
     * applicable Novell product.
     *
     * THE WORK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
     * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
     * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE WORK OR THE USE OR OTHER DEALINGS IN THE WORK.
     */
    
    package com.novell.nds.dirxml.driver.soap.examples;
    
    import org.w3c.dom.Element;
    
    import java.util.Properties;
    import com.novell.nds.dirxml.driver.soap.util.SchemaReporter;
    import com.novell.nds.dirxml.driver.soap.util.Tracer;
    
    public class SchemaReporterExample implements SchemaReporter {
        Tracer tracer = null;
    
        /**
         * The init method is called by the driver when this class is first instantiated. This method will only be called
         * once.
         * @param parameterString
         * @param tracer An instance of an object implementing the Tracer interface.
         *               Use the trace method of this object to send messages to DSTrace.
         * @return       A Properties object for communicating with the driver shim. The only property defined at this time
         *               is "secure" which indicates whether or not this extension transports or stores data in the clear.
         * @see com.novell.nds.dirxml.driver.soap.util.Extension#init(String, Tracer)
         */
        public Properties init(String parameterString, Tracer tracer) {
            this.tracer = tracer;
            tracer.trace("DocumentModifiersExample.init() init string; " + parameterString);
    
            // Process the parameterString here. You can control what is in the parameterString by setting the appropriate
            // "Init Parameter" setting in the configuration. See the driver documentation for more details.
    
            // Before the init method returns, we must create a Properties object that contains the properties defined for
            // communicating with the driver shim. So far, only "secure" has been defined and should have the value "false"
            // if this extension will transport or store data insecurely.
            Properties properties = new Properties();
            properties.put("secure", "true");
            return properties;
        }
    
        /**
         * This method will be called whenever the getSchema method of DriverShim is called by the DirXML engine. You are
         * passed the DOM Element corresponding to the <schema-def> element in the XML document that will be
         * returned to the engine. All you are required to do is add child elements to the schemaDefElements element that
         * correspond to the application schema, and then return.
         *
         * @param schemaDefElement the Element corresponding to the <schema-def> element in the XML document that
         * will be returned to the engine.
         */
        public void getSchema(Element schemaDefElement) {
            //todo
        }
    }
    
  • 0   in reply to   

    To build it, you can use a Maven POM like this.
    First add all the necessary JARs to a project local Maven repo, e.g. for dirxml.jar (adjust version number as necessary):

    mvn deploy:deploy-file -Durl=file://repo -Dfile=
    /opt/novell/eDirectory/lib/dirxml/classes/dirxml.jar -DgroupId=com.novell.nds -DartifactId=dirxml -Dpackaging=jar -Dversion=4.8.0.0

    POM

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.novell.nds.dirxml</groupId>
      <artifactId>soap-examples</artifactId>
      <version>1.0.0</version>
      <packaging>jar</packaging>
    
      <name>NetIQ IDM - Java extensions to drivers</name>
      <url>https://www.netiq.com/documentation/identity-manager-developer/</url>
    
      <properties>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.source>1.8</maven.compiler.source>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
    
      <repositories>
        <repository>
          <id>project.local</id>
          <name>project</name>
          <url>file:${project.basedir}/repo</url>
        </repository>
        <repository>
          <id>central</id>
          <name>Central Repository</name>
          <url>https://repo.maven.apache.org/maven2</url>
          <layout>default</layout>
          <snapshots>
            <enabled>false</enabled>
          </snapshots>
        </repository>
      </repositories>
      <build>
        <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.2</version>
            <configuration>
              <source>1.8</source>
              <target>1.8</target>
            </configuration>
          </plugin>
        </plugins>
      </build>
      <dependencies>
        <dependency>
          <groupId>com.novell</groupId>
          <artifactId>nxsl</artifactId>
          <version>4.6.0.0</version>
        </dependency>
        <dependency>
          <groupId>com.novell.nds</groupId>
          <artifactId>dirxml</artifactId>
          <version>4.8.0.0</version>
        </dependency>
        <dependency>
          <groupId>com.novell.nds</groupId>
          <artifactId>dirxml_misc</artifactId>
          <version>4.8.0.0</version>
        </dependency>
        <dependency>
          <groupId>com.novell.nds.dirxml.driver</groupId>
          <artifactId>SOAPUtil</artifactId>
          <version>4.0.0.4</version>
        </dependency>
        <dependency>
          <groupId>com.novell.nds.dirxml.driver</groupId>
          <artifactId>DelimitedTextUtil</artifactId>
          <version>4.0.2.0</version>
        </dependency>
        <dependency>
          <groupId>com.novell.nds.dirxml.driver</groupId>
          <artifactId>RESTUtil</artifactId>
          <version>1.0.0.1</version>
        </dependency>
        <dependency>
          <groupId>com.novell.nds.dirxml.driver</groupId>
          <artifactId>SCIMUtils</artifactId>
          <version>1.0.1-0300</version>
        </dependency>
      </dependencies>
    
    </project>

  • 0 in reply to   

    Thanks for the great help.

    Im now in the middle of coding and just wondering if theres a optimized way for me to work.

    When i make a new jar file and put it in the classes folder - i need (is my understanding) to restart eDirctory for the new version to be recognized by the driver.

    I know I can write and test allot of my code locally and debug my way through, but -are there a faster way to deploy the new jar file or am i forced to ndsmanage stopall; ndsmanage startall, every time i want to try out my new jarfile?

  • 0   in reply to 

    Assuming you are on Linux, install the Remote Loader on the engine server.  Set up the connection as a Remote Loader, hosted on the Engine server.  This works very nicely and now restart rdxml whenever you need to.

    In this case, should use the Java Remote Loader ,not the RPM packaged Remote loader, because that one tries to play nice and assume file paths the same as in eDir.  The Java one lets you manage the start script and specify paths and whatnot.

  • 0   in reply to   

    Whilst I was doing development of a SOAP java extension many moons ago. I found it even better to configure this in-development driver with an additional java class path to a separate directory that contained only the JAR that I was working on. This was on top of the default class paths that the remote loader set.

    This kept my own development work separate from the NetIQ default java classes and avoided my code being inadvertently loaded by other IDM components.

    In that case, was a windows-only environment, where the TEST remote loader server had multiple drivers configured - including several SOAP drivers. I only wanted my extension to apply to one specific driver.