Blog

Querying Active Directory from Java using ADSI

Software development

In order to query a user's Active Directory properties from a Java application, we have a couple of possibilities. The most obvious option is to directly query using an LDAP connection through JNDI. Since Active Directory, by default, does not support anonymous binds, this requires a user account in the AD domain, storing/maintaining the user account in the application configuration, and a simple or Kerberos bind on the LDAP connection. All doable, but why not use the computer's domain credentials (assuming the computer is part of the AD domain)?

To use the computer's domain credentials (and not require any configuration of credentials in the application itself), we can use the Active Directory Service Interface (ADSI), which is a set of COM interfaces, accessible using ActiveX Data Objects (ADO). For this, we need to use JNI and Jacob (Java - Com bridge), for which the documentation is quite poor. To help you out, here is some code and the right dependencies.

First of all, include the following dependencies in your project (Gradle style syntax):

dependencies {
    // Jacob and accompanying wrappers (from own at http://www.eveoh.nl/files/maven2/)
    compile 'net.sf.jacob-project:jacob:1.15-M4'
    compile 'net.sf.jacob-project:jacob-ado-wrappers:1.0' // ADO wrappers, available from the Jacob source package, under GPLv3, repacked to nl.eveoh.jacob.ado namespace
}

A small example to retrieve the employeeNumber attribute from the current AD domain:

import nl.eveoh.jacob.ado.*;
import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;
import com.jacob.com.Variant;

public class MyClass {

    private String getEmployeeNumber(String username) {
        try {
            ComThread.InitMTA(); // Init a multithread environment for COM, and close it afterwards to release all COM objects

            Connection conn = new Connection(); // Create an ADO connection to an ADSI object
            conn.setProvider("ADsDSOObject");
            conn.Open();

            Command command = new Command();
            command.setActiveConnection(conn);
            command.setCommandType(CommandTypeEnum.adCmdText);

            ActiveXComponent ax = new ActiveXComponent("LDAP://RootDSE"); // Get the default naming context for the LDAP query
            Variant v = Dispatch.call(ax, "Get", "defaultNamingContext");
            String dnc = v.toString();

            // Create the LDAP query and retrieve the result
            String ldapStr = "<LDAP://" + dnc + ">;(&(objectClass=user)(samAccountName=" + username
                    + "));employeeNumber;subtree";
            command.setCommandText(ldapStr);

            Recordset rs = command.Execute();
            Fields fs = rs.getFields();

            if (rs.getEOF()) {
                return null;
            }

            rs.MoveFirst();
            return fs.getItem(0).getValue().toString();
        }
        finally {
            ComThread.Release();
        }
    }

}
Drop me a mail if you have any questions or remarks!

Using Google Web Toolkit with Gradle

MyTimetable, Software development

Recently, we switched to Gradle as build tool of MyTimetable. Previously, we have been using Ant. While Ant certainly is a good build tool (Gradle uses Ant internally), it lacks declarative dependency management. To introduce declarative dependency management we have considered a couple of options: Ivy (with Ant), Maven or Gradle. In the end we went with Gradle, because it offers the most flexibility with the least amount of work involved. Maven leads to an XML/plugin hell for certain custom scenarios, and Ivy/Ant lacks good multi-project support (sure you can have multiple projects with Ivy/Ant, but you have to do all the hard work yourself).

We are currently using a custom build of Gradle 1.0-milestone-7 (with a fix for GRADLE-1881, available at GitHub or as binary compile). Together with STS's quite cool Gradle support, this gives us everything we need.

In the MyTimetable project we make extensive use of the Google Web Toolkit (GWT) for the client-side interface. When deploying to production, GWT requires a compile, where the client-side Java code is compiled to Javascript. Gradle does not provide out-of-the-box support for this compile, but it's as simple as calling the right Java program with the right arguments. There is also a complete Gradle GWT plugin available, but it's still work-in-progress and supports more than we need (like the GWT dev mode), so we decided to do it ourselves in Gradle. The following dependencies are necessary for GWT, include them in your gradle.build:

dependencies {
    // Compile GWT libs, needed for gwtCompile and the javaCompile
    // Also includes the servlet-api
    providedCompile 'com.google.gwt:gwt-user:2.4.0'
    providedCompile 'com.google.gwt:gwt-dev:2.4.0'
    
    // Needed for GWT compile and at runtime for RequestBuilder
    // Specify two artifacts as workaround for GRADLE-1934
    compile('javax.validation:validation-api:1.0.0.GA') { 
        artifact {
            name = 'validation-api'
            type = 'jar'
        }
        artifact {
            name = 'validation-api'
            type = 'jar'
            classifier = 'sources'
        }
    }
    
    // Runtime GWT libraries, should be included in WAR
    runtime 'com.google.gwt:gwt-servlet:2.4.0'
    runtime 'org.json:json:20090211'
}

In order to compile the GWT code to Javascript, we introduce an compileGwt Gradle task and let the war task depend on this task:

task compileGwt (dependsOn: classes, type: JavaExec) {
    buildDir = "${project.buildDir}/gwt"
    extraDir = "${project.buildDir}/extra"
    
    inputs.source sourceSets.main.java.srcDirs
    inputs.dir sourceSets.main.output.resourcesDir
    outputs.dir buildDir
    
    // Workaround for incremental build (GRADLE-1483)
    outputs.upToDateSpec = new org.gradle.api.specs.AndSpec()
    
    doFirst {
        file(buildDir).mkdirs()
    }
    
    main = 'com.google.gwt.dev.Compiler'
    
    classpath {
        [
            sourceSets.main.java.srcDirs,           // Java source
            sourceSets.main.output.resourcesDir,    // Generated resources
            sourceSets.main.output.classesDir,      // Generated classes
            sourceSets.main.compileClasspath,       // Deps
        ]   
    }
    
    args =
        [
            'nl.eveoh.scheduleviewer.Scheduleviewer', // Your GWT module
            '-war', buildDir,
            '-logLevel', 'INFO',
            '-localWorkers', '2',
            '-compileReport', 
            '-extra', extraDir,
            // '-draftCompile' // Speeds up compile with 25%
        ]
        
    maxHeapSize = '256M'
}

war.dependsOn compileGwt
war {
    from compileGwt.buildDir
}

The compileGwt task will be called automatically and the contents will be included in the generated war file. Also the GWT compile we only be run if the contents of the class or resource files have changed. And in case you use the Eclipse plugin, the right nature, buildcommand and classpath can be added automatically by the Eclipse task:

eclipse {
    project {
        natures 'com.google.gwt.eclipse.core.gwtNature'
        buildCommand 'com.google.gdt.eclipse.core.webAppProjectValidator'
        buildCommand 'com.google.gwt.eclipse.core.gwtProjectValidator'        
    }
    classpath {
        containers 'com.google.gwt.eclipse.core.GWT_CONTAINER'
    }
}

I hope this info is helpful, let us know if you have any suggestions, remarks or problems. Happy Gradling!

XCal output with iCal4j

MyTimetable, Software development

One of our customers asked us to implement an xCal export in MyTimetable to link their upcoming mobile platform to students' schedules. xCal is basically iCalender, but in an XML format.

For the iCalendar export of MyTimetable we use the great open source Java library iCal4j. This library provides a complete iCalendar object model and the ability to verify and write iCalendar files. Unfortunately, the iCalendar export is hard coded into the model, but it is possible to create your own outputter.

We took the liberty to implement an XmlOutputter, using StAX to generate the XML. Since we wanted to keep the code simple and easily distributable, we chose to keep all the logic in the XmlOutputter, without depending on any Java-to-XML mapping frameworks. Software engineering wise nicer solutions may be possible. Another problem is that the iCalendar data value type of components cannot be easily retrieved from the iCal4j object model (since it is not necessary for the usual iCalendar export), so that information is hard coded into the XmlOutputter.

Source of the XmlOutputter is available at http://www.eveoh.nl/files/XmlOutputter.java and can be freely used (public domain). Since we do not use every component type, we cannot guarantee all possible options work correctly. Let us know if you have any suggestions.