Complex projects are usually managed by breaking the project into sub-projects, a.k.a. "modules". It often happens that the objects/classes that need to be exposed as part of a public Web service API reside in a different module than that of the Web service endpoint classes that expose them.
As an example, consider the case where we have a set of data access objects (DAOs) that are mapped directly into rows in the database through an ORM technology such as JPA. Usually, these objects are managed by a set of domain classes that handle the business logic around the behavior of these objects. Perhaps there are multiple sets of such objects, grouped into different modules based on different areas of concern.
The basic idea is that we have a set of modules that contain objects that we want to expose as part of the Web service API. The Web service endpoint classes reside in a separate module.
As of Enunciate 1.12, objects that are statically referenced by Web service endpoint classes are automatically discovered as part of the Web service API. Enunciate uses JAXB's definition of statically referenced, including honoring the @XmlSeeAlso annotation on any endpoint class.
However, you'll quickly notice that any classes that reside in modules different from the module to which Enunciate has been applied are missing the documentation on other goodies that you get when you invoke Enunciate directly on the Java source code. This is because if only the compiled classes are supplied to Enunciate, it can't leverage any information found in the original Java source code.
Importing API Classes
In order for Enunciate to leverage the additional goodies found in the original Java source code, you've got to provide Enunciate with additional information about these classes. This is referred to as "importing" API classes.
The process for importing API classes is fairly straightforward:
- Specify which classes are to be imported.
- Make the Java source code available on the classpath.
Specifying Import Classes
Classes to be imported are specified in the Enunciate configuration file with the "api-import" element. The "api-import" element takes an attribute, "pattern" that can be used to specify the classes to be imported. The pattern is an Ant-style pattern with '.' being the path separator character. Enunciate will scan the classpath and apply the pattern(s) to the fully-qualified name of the classes to determine which classes are to be imported. Consider this example:
This will tell Enunciate to import all classes in the "com.mycompany.pck1.dao" package, all classes in the "com.mycompany.pck2" and any of its subpackages, the "com.mycompany.pck3.MyClass" class, and the "com.mycompany.pck3.MyClass.MyInnerClass". Note that inner classes, for the purposes of applying the pattern, are considered as if they would be in the package named by their container class; if the pattern "com.mycompany.pck3.MyClass.MyInnerClass" were not specified, the "com.mycompany.pck3.MyClass.MyInnerClass" class would not be imported.
Making the Java Source Available
For all imported classes (and only for imported classes) Enunciate will also scan the classpath for an associated Java source file. If the Java source file exists on the classpath in the same place (i.e. same directory) where the compiled class would be expected, Enunciate will use the source file to generate the API and its documentation instead of the compiled class.
Maven is especially suited to support multi-module Enunciate projects. For this example, consider a module named "domain" that contains classes that are to be imported into an Enunciate-supported war module named "webapp". In the
pom.xml for the domain module, just leverage the
maven-source-plugin to attach the source jar to the module:
Source Jar Dependency (release 1.15 and earlier)
pom.xml for the webapp module, just add the optional source jar as a dependency of the project with compile-time scope:
Exporting API Classes
Using the Enunciate configuration file is not the only way to import classes. Any classes that are "exported" will be automatically imported.
The export process is done by creating a file that consists of a newline-separated list of the exported classes that will be available on the Enunciate classpath at the entry "META-INF/enunciate/api-exports". Enunciate will query for this file(s) and add each of the exports to the public API.
Maven Support for Exporting Classes
For Maven users, there exists a Maven plugin that can be used to export API classes for later use in an Enunciate project. The plugin is for use with "jar" packaging and will add the "enunciate/api-exports" file to the "META-INF" directory of the created jar. Your classes will be brought through the standard Enunciate validation process.
Example POM snippet:
This will export all API classes in the created jar artifact so that any Enunciate project with a dependency on this artifact will automatically import those exported classes.