users@jersey.java.net

Re: [Jersey] WADL + Ant

From: cquiroz <carlos.m.quiroz_at_gmail.com>
Date: Mon, 2 Mar 2009 06:16:42 -0800 (PST)

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?

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;
> }
> }
>
>
>

-- 
View this message in context: http://n2.nabble.com/WADL-%2B-Ant-tp2240710p2409364.html
Sent from the Jersey mailing list archive at Nabble.com.