users@jersey.java.net

Re: [Jersey] WADL + Ant

From: Martin Grotzke <martin.grotzke_at_freiheit.com>
Date: Mon, 02 Mar 2009 18:28:26 +0100

On Mon, 2009-03-02 at 06:16 -0800, cquiroz wrote:
> Hi
>
> Thanks a lot, this worked, I really like the concept of generating the
> documentation in one go from the source code.
>
> One question. I have a resource that can return either xml or json but if I
> use the extended javadoc tags I can only document one of them. Is there a
> good way to solve this?
Hmm, it seems that this is currently not possible. I have to think about
it a little bit.

I asume you have a single method that returns different content types,
right? So you'd need s.th. like
  @response.representation.200.application/json.doc
and
  @response.representation.200.application/xml.doc ?

Cheers,
Martin



>
> Regards
> Carlos
>
>
> Martin Grotzke-2 wrote:
> >
> > You should use the task provided by Andrew. I'm not sure if he sent it
> > to this list once, however I have it attached to this mail (it's still
> > on my commit queue to the contribs stuff).
> >
> > The task-def might look like this (if you're using jdk 1.5 you should
> > add jaxb-api-2.1.jar):
> >
> > <taskdef name="generatewadl"
> > classname="com.sun.jersey.wadl.GenerateWadlTask">
> > <classpath>
> > <fileset dir="${maven.repo.local}">
> > <include
> > name="com/sun/jersey/contribs/ant-wadl-task/${jersey-release-version}/ant-wadl-task-${jersey-release-version}.jar"/>
> > <include
> > name="com/sun/jersey/jersey-server/${jersey-release-version}/jersey-server-${jersey-release-version}.jar"/>
> > <include
> > name="com/sun/jersey/jersey-core/${jersey-release-version}/jersey-core-${jersey-release-version}.jar"/>
> > <include name="javax/ws/rs/jsr311-api/1.0/jsr311-api-1.0.jar"/>
> > <include name="xerces/xercesImpl/2.6.1/xercesImpl-2.6.1.jar"/>
> > <include name="asm/asm/3.1/asm-3.1.jar"/>
> > </fileset>
> > </classpath>
> > </taskdef>
> >
> > The target should look like this:
> >
> > <target name="wadl" depends="compile, resourcedoc" description="Generate
> > wadl doc">
> > <mkdir dir="${maven.build.dir}" />
> > <generatewadl wadlFile="${maven.build.dir}/application.wadl"
> > formatWadlFile="true" baseUri="http://www.example.org">
> > <classpath>
> > <!-- have to add the path to your compiled resources as well!
> > -->
> > <pathelement location="${maven.build.outputDir}" />
> > <path refid="build.classpath.fixed" />
> > </classpath>
> > <packages>
> > <package name="com.sun.jersey.samples.generatewadl.resources"
> > />
> > </packages>
> > <wadlGenerators>
> > <wadlGeneratorDescription
> > name="com.sun.jersey.server.wadl.generators.resourcedoc.WadlGeneratorResourceDocSupport">
> >
> > </wadlGeneratorDescription>
> > </wadlGenerators>
> > </generatewadl>
> > </target>
> >
> > Please change all file references and variables to your needs.
> >
> > Cheers,
> > Martin
> >
> >
> > On Fri, 2009-02-27 at 00:53 -0800, cquiroz wrote:
> >> Hi
> >>
> >> I just copied the build.xml snippet and it works for the most part
> >> except adding the xml file generated using the ResourcedDoclet
> >>
> >> <generatewadl wadlFile="${build}/classes/
> >> wadl/application.wadl"
> >> formatWadlFile="true" baseUri="<base_uri>">
> >> <wadlGenerators>
> >> <wadlGeneratorDescription
> >> name="com.sun.jersey.server.wadl.generators.resourcedoc.WadlGeneratorResourceDocSupport">
> >>
> >> </wadlGeneratorDescription>
> >> </wadlGenerators>
> >> </generatewadl>
> >>
> >> The task available in jersery 1.0.2 doesn't suppport the
> >> <wadlGenerators> element
> >>
> >> Carlos
> >>
> >>
> >> On Fri, Feb 27, 2009 at 1:08 AM, Andrew Ochsner (via Nabble) <ml-user%
> >> 2B110154-694370125@...> wrote:
> >> I'm also happy to dive in and help as I created and have been
> >> using it for a bit now... While I totally know it's limited
> >> (does just enough for me but thought it was good enough that
> >> others might find it useful).
> >>
> >> So the example I gave is exactly what I have and it works fine
> >> using the extended javadoc tags.
> >>
> >> Not sure what you mean that it doesn't support hte sub
> >> component wadlGenerators...could you maybe post the snippet of
> >> your build.xml?
> >>
> >> Thanks
> >> Andy O
> >>
> >>
> >> On Thu, Feb 26, 2009 at 7:45 AM, Paul Sandoz <Paul.Sandoz@...>
> >> wrote:
> >>
> >> On Feb 26, 2009, at 12:15 PM, cquiroz wrote:
> >>
> >>
> >> Hi
> >>
> >> First of all thanks to all the jersey authors,
> >> this is one of the most
> >> enjoyable frameworks I have ever used, great
> >> design!
> >>
> >>
> >>
> >> Thanks!
> >>
> >>
> >>
> >> Now into my question, I tried to follow the
> >> ant task example as below since
> >> I want to create the REST documentation based
> >> on the code.
> >>
> >> However, the current code (jersey 1.0.2)
> >> doesn't work as indicated below. I
> >> can correctly create the docs but to use the
> >> extended javadoc tags I'd need
> >> to pass the resource.xml file as indicated in
> >> this example.
> >>
> >> It seems that the wadl task in 1.0.2 doesn't
> >> support the sub component
> >> wadlGenerators.
> >>
> >>
> >> Yes, the Ant task is rather limited.
> >>
> >>
> >>
> >> Do you have any suggestions, is this coming in
> >> the next
> >> version?
> >>
> >>
> >>
> >> Could you log an issue. We will try and fix it for the
> >> next release (end of March start of April time-frame).
> >>
> >> Thanks,
> >> Paul.
> >>
> >>
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscribe@...
> >> For additional commands, e-mail: users-help@...
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >> ______________________________________________________________________
> >> View this message in context: Re: [Jersey] WADL + Ant
> >> Sent from the Jersey mailing list archive at Nabble.com.
> > --
> > Martin Grotzke
> > http://www.javakaffee.de/blog/
> >
> > package com.sun.jersey.wadl;
> >
> > import java.io.BufferedOutputStream;
> > import java.io.File;
> > import java.io.FileNotFoundException;
> > import java.io.FileOutputStream;
> > import java.io.OutputStream;
> > import java.lang.reflect.Constructor;
> > import java.lang.reflect.InvocationTargetException;
> > import java.lang.reflect.Method;
> > import java.util.ArrayList;
> > import java.util.HashMap;
> > import java.util.HashSet;
> > import java.util.List;
> > import java.util.Map;
> > import java.util.Set;
> >
> > import javax.xml.bind.JAXBContext;
> > import javax.xml.bind.Marshaller;
> >
> > import org.apache.tools.ant.AntClassLoader;
> > import org.apache.tools.ant.BuildException;
> > import org.apache.tools.ant.Task;
> > import org.apache.tools.ant.types.Path;
> > import org.apache.tools.ant.types.Reference;
> > import org.apache.xml.serialize.OutputFormat;
> > import org.apache.xml.serialize.XMLSerializer;
> >
> > import com.sun.jersey.api.core.PackagesResourceConfig;
> > import com.sun.jersey.api.core.ResourceConfig;
> > import com.sun.jersey.api.model.AbstractResource;
> > import
> > com.sun.jersey.server.impl.modelapi.annotation.IntrospectionModeller;
> > import com.sun.jersey.server.wadl.WadlBuilder;
> > import com.sun.jersey.server.wadl.WadlGenerator;
> > import com.sun.jersey.server.wadl.WadlGeneratorImpl;
> > import com.sun.research.ws.wadl.Application;
> >
> > /**
> > * This ant task generates a wadl file, using an option resourcedoc file
> > created
> > * by the {_at_link ResourceDoclet} and an applicationdoc file.<br />
> > * Created on: Jun 18, 2008<br />
> > *
> > * @author Andrew Ochsner
> > * @version $Id$
> > *
> > */
> > public class GenerateWadlTask extends Task {
> >
> > public static class Package {
> > private String name;
> >
> > public Package() {
> >
> > }
> >
> > public String getName() {
> > return name;
> > }
> >
> > public void setName(String name) {
> > this.name = name;
> > }
> > }
> >
> > public static class Packages {
> > public Packages() {
> > packages = new ArrayList<Package>();
> > }
> >
> > public Package createPackage() {
> > Package _package = new Package();
> > packages.add(_package);
> > return _package;
> > }
> >
> > public List<Package> getPackages() {
> > return packages;
> > }
> >
> > private List<Package> packages;
> > }
> >
> > public static class WadlGeneratorInfoParam {
> > private String name;
> > private String value;
> >
> > public WadlGeneratorInfoParam() {
> >
> > }
> >
> > public String getName() {
> > return name;
> > }
> >
> > public void setName(String name) {
> > this.name = name;
> > }
> >
> > public String getValue() {
> > return value;
> > }
> >
> > public void setValue(String value) {
> > this.value = value;
> > }
> > }
> >
> > public static class WadlGeneratorInfo {
> > private String name;
> > private List<WadlGeneratorInfoParam> params;
> >
> > public WadlGeneratorInfo() {
> > params = new ArrayList<WadlGeneratorInfoParam>();
> > }
> >
> > public String getName() {
> > return name;
> > }
> >
> > public void setName(String name) {
> > this.name = name;
> > }
> >
> > public List<WadlGeneratorInfoParam> getParams() {
> > return params;
> > }
> >
> > public WadlGeneratorInfoParam createParam() {
> > WadlGeneratorInfoParam param = new WadlGeneratorInfoParam();
> > params.add(param);
> > return param;
> > }
> > }
> >
> > public static class WadlGenerators {
> > private List<WadlGeneratorInfo> wadlGeneratorDescriptions;
> >
> > public WadlGenerators() {
> > wadlGeneratorDescriptions = new ArrayList<WadlGeneratorInfo>();
> > }
> >
> > public WadlGeneratorInfo createWadlGeneratorDescription() {
> > WadlGeneratorInfo info = new WadlGeneratorInfo();
> > wadlGeneratorDescriptions.add(info);
> > return info;
> > }
> >
> > public List<WadlGeneratorInfo> getWadlGeneratorDescriptions() {
> > return wadlGeneratorDescriptions;
> > }
> > }
> >
> > /**
> > * Location of the wadl file to create.
> > *
> > * @parameter property="wadlFile"
> > * expression="${project.build.directory}/application.wadl"
> > * @required
> > */
> > private File _wadlFile;
> >
> > /**
> > * Specifies, if the generated wadl file shall contain formatted xml or
> > not.
> > * The default value is <code>true</code>.
> > *
> > * @parameter property="formatWadlFile"
> > */
> > private boolean _formatWadlFile = true;
> >
> > /**
> > * The base-uri to use.
> > *
> > * @parameter property="baseUri"
> > * @required
> > */
> > private String _baseUri;
> >
> > /**
> > * A list of packages that is searched for resource classes
> > *
> > * @paramter property="packages"
> > * @required
> > */
> > private Packages _packages;
> >
> > /**
> > * A list of wadl generators to run
> > *
> > * @parameter property="wadlGenerators"
> > * @required
> > */
> > private WadlGenerators _wadlGenerators;
> >
> > /**
> > * @parameter property="classpathref"
> > * @required
> > */
> > private Path _classpath;
> >
> > @Override
> > public void execute() throws BuildException {
> > if (_packages == null || _packages.getPackages().size() == 0) {
> > throw new BuildException(
> > "A fileset of resources is required but not defined.");
> > }
> > if (_wadlFile == null) {
> > throw new BuildException(
> > "The wadlFile attribute is required but not defined.");
> > }
> >
> > if (_baseUri == null || _baseUri.length() == 0) {
> > throw new BuildException(
> > "The baseUri attribute is required but not defined.");
> > }
> > AntClassLoader classLoader = null;
> > try {
> >
> > classLoader = getProject().createClassLoader(_classpath);
> > classLoader.setParent(this.getClass().getClassLoader());
> > classLoader.setThreadContextLoader();
> > com.sun.jersey.server.wadl.WadlGenerator wadlGenerator = new
> > WadlGeneratorImpl();
> > if (_wadlGenerators != null) {
> > for (WadlGeneratorInfo wadlGeneratorInfo : _wadlGenerators
> > .getWadlGeneratorDescriptions()) {
> > wadlGenerator = loadWadlGenerator(wadlGeneratorInfo,
> > wadlGenerator);
> > }
> > }
> > wadlGenerator.init();
> >
> > final Application a = createApplication(wadlGenerator);
> > a.getResources().setBase(_baseUri);
> > final JAXBContext c = JAXBContext.newInstance(wadlGenerator
> > .getRequiredJaxbContextPath(), Thread.currentThread()
> > .getContextClassLoader());
> > final Marshaller m = c.createMarshaller();
> > m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, _formatWadlFile);
> > final OutputStream out = new BufferedOutputStream(
> > new FileOutputStream(_wadlFile));
> >
> > final XMLSerializer serializer = getXMLSerializer(out);
> >
> > m.marshal(a, serializer);
> > out.close();
> >
> > log("Wrote " + _wadlFile);
> >
> > } catch (Exception e) {
> > if (classLoader != null) {
> > classLoader.resetThreadContextLoader();
> > classLoader.cleanup();
> > }
> >
> > throw new BuildException("Could not write wadl file", e);
> > }
> > }
> >
> > private XMLSerializer getXMLSerializer(OutputStream out)
> > throws FileNotFoundException {
> > // configure an OutputFormat to handle CDATA
> > OutputFormat of = new OutputFormat();
> >
> > // specify which of your elements you want to be handled as CDATA.
> > // The use of the '^' between the namespaceURI and the localname
> > // seems to be an implementation detail of the xerces code.
> > // When processing xml that doesn't use namespaces, simply omit the
> > // namespace prefix as shown in the third CDataElement below.
> > of.setCDataElements(new String[] {
> > "http://research.sun.com/wadl/2006/10^doc", // <ns1:foo>
> > "ns2^doc", // <ns2:bar>
> > "^doc"
> > /*
> > * , "ns2:doc", "doc"
> > */}); // <baz>
> >
> > // set any other options you'd like
> > of.setPreserveSpace(true);
> > of.setIndenting(true);
> > // of.setLineWidth( 120 );
> > // of.setNonEscapingElements( new String[] {
> > // "http://www.w3.org/1999/xhtml^br", "http://www.w3.org/1999/xhtml^br"
> > // } );
> >
> > // create the serializer
> > XMLSerializer serializer = new XMLSerializer(of);
> >
> > serializer.setOutputByteStream(out);
> >
> > return serializer;
> > }
> >
> > private WadlGenerator loadWadlGenerator(
> > WadlGeneratorInfo wadlGeneratorInfo,
> > com.sun.jersey.server.wadl.WadlGenerator wadlGeneratorDelegate)
> > throws Exception {
> > log("Loading wadlGeneratorInfo " + wadlGeneratorInfo.getName());
> > final Class<?> clazz = Class.forName(wadlGeneratorInfo.getName(), true,
> > Thread.currentThread().getContextClassLoader());
> > final WadlGenerator generator = clazz.asSubclass(WadlGenerator.class)
> > .newInstance();
> > generator.setWadlGeneratorDelegate(wadlGeneratorDelegate);
> > if (!wadlGeneratorInfo.getParams().isEmpty()) {
> > for (WadlGeneratorInfoParam param : wadlGeneratorInfo.getParams()) {
> > setProperty(generator, param.getName(), param.getValue());
> > }
> > }
> > return generator;
> > }
> >
> > private void setProperty(final Object object, final String propertyName,
> > final Object propertyValue) throws IllegalAccessException,
> > InvocationTargetException, NoSuchMethodException,
> > InstantiationException {
> > final String methodName = "set"
> > + propertyName.substring(0, 1).toUpperCase()
> > + propertyName.substring(1);
> > final Method method = getMethodByName(methodName, object.getClass());
> > if (method.getParameterTypes().length != 1) {
> > throw new RuntimeException(
> > "Method "
> > + methodName
> > + " is no setter, it does not expect exactly one parameter, but "
> > + method.getParameterTypes().length);
> > }
> > final Class<?> paramClazz = method.getParameterTypes()[0];
> > if (paramClazz == propertyValue.getClass()) {
> > method.invoke(object, propertyValue);
> > } else {
> > /*
> > * does the param class provide a constructor for string?
> > */
> > final Constructor<?> paramTypeConstructor = paramClazz
> > .getConstructor(propertyValue.getClass());
> > if (paramTypeConstructor != null) {
> > final Object typedPropertyValue = paramTypeConstructor
> > .newInstance(propertyValue);
> > method.invoke(object, typedPropertyValue);
> > } else {
> > throw new RuntimeException(
> > "The property '"
> > + propertyName
> > + "' could not be set"
> > + " because the expected parameter is neither of type "
> > + propertyValue.getClass()
> > + " nor of any type that provides a constructor expecting a "
> > + propertyValue.getClass() + "."
> > + " The expected parameter is of type "
> > + paramClazz.getName());
> > }
> > }
> > }
> >
> > private Method getMethodByName(final String methodName, final Class<?>
> > clazz) {
> > for (Method method : clazz.getMethods()) {
> > if (method.getName().equals(methodName)) {
> > return method;
> > }
> > }
> > throw new RuntimeException("Method '" + methodName
> > + "' not found for class " + clazz.getName());
> > }
> >
> > private Application createApplication(WadlGenerator wadlGenerator) {
> > final Map<String, Object> map = new HashMap<String, Object>();
> > List<String> packageNames = new ArrayList<String>();
> > for (Package p : _packages.getPackages()) {
> > packageNames.add(p.getName());
> > }
> > map.put(PackagesResourceConfig.PROPERTY_PACKAGES, packageNames
> > .toArray(new String[] {}));
> > final ResourceConfig rc = new PackagesResourceConfig(map);
> > final Set<AbstractResource> s = new HashSet<AbstractResource>();
> > for (Class<?> c : rc.getRootResourceClasses()) {
> > log("Adding class " + c.getName());
> > s.add(IntrospectionModeller.createResource(c));
> > }
> > return new WadlBuilder(wadlGenerator).generate(s);
> > }
> >
> > public void setWadlFile(File file) {
> > _wadlFile = file;
> > }
> >
> > public void setFormatWadlFile(boolean wadlFile) {
> > _formatWadlFile = wadlFile;
> > }
> >
> > public void setBaseUri(String uri) {
> > _baseUri = uri;
> > }
> >
> > public void setClasspath(Path path) {
> > if (_classpath == null) {
> > _classpath = path;
> > } else {
> > _classpath.append(path);
> > }
> > }
> >
> > public Path createClasspath() {
> > if (_classpath == null) {
> > _classpath = new Path(getProject());
> > }
> > return _classpath.createPath();
> > }
> >
> > public void setClasspathRef(Reference r) {
> > createClasspath().setRefid(r);
> > }
> >
> > public Packages createPackages() {
> > if (_packages == null) {
> > _packages = new Packages();
> > }
> > return _packages;
> > }
> >
> > public WadlGenerators createWadlGenerators() {
> > if (_wadlGenerators == null) {
> > _wadlGenerators = new WadlGenerators();
> > }
> > return _wadlGenerators;
> > }
> > }
> >
> >
> >