<?xml version="1.0" encoding="UTF-8"?>
<!-- 
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
                         "http://www.docbook.org/xml/4.4/docbookx.dtd">
 -->
<chapter id="WADL">
    <title>RESTEasy WADL Support</title>
    <para>RESTEasy has support to generate WADL for its resources. It supports several different containers.
        The following text shows how to use this feature in different containers.
    </para>
    <section>
        <title>RESTEasy WADL Support for Servlet Container(Deprecated)</title>
        <note>
            <para>
                The content introduced in this section is outdated, and the <code>ResteasyWadlServlet</code> class is deprecated because it doesn't support the GRAMMAR generation. Please check the <code>ResteasyWadlDefaultResource</code> introduced in the later section.
            </para>
        </note>
        <para>
            RESTEasy WADL uses ResteasyWadlServlet to support servlet container. It must be registered in the
            web.xml to enable WADL feature. Here is an example to show the usages of ResteasyWadlServlet in web.xml:
        </para>
        <programlisting><![CDATA[<servlet>
	<servlet-name>RESTEasy WADL</servlet-name>
	<servlet-class>org.jboss.resteasy.wadl.ResteasyWadlServlet</servlet-class>
</servlet>

<servlet-mapping>
	<servlet-name>RESTEasy WADL</servlet-name>
	<url-pattern>/application.xml</url-pattern>
</servlet-mapping>
]]></programlisting>
        <para>
            The preceding configuration in web.xml shows how to enable ResteasyWadlServlet and map it
            to /application.xml, so then the WADL can be accessed from the configured URL:
        </para>
        <programlisting><![CDATA[/application.xml]]></programlisting>
    </section>
    <section>
    <title>RESTEasy WADL Support for Servlet Container(Updated)</title>
        <para>
            This section introduces the recommended way to enable WADL support in a Servlet Container.
            First, add a class that extends the <code>ResteasyWadlDefaultResource</code> to
            serve a resource path. Here is an example:
        </para>
        <programlisting><![CDATA[import org.jboss.resteasy.wadl.ResteasyWadlDefaultResource;
import jakarta.ws.rs.Path;

@Path("/")
public class MyWadlResource extends ResteasyWadlDefaultResource {
}]]></programlisting>
        <para>As the sample shows above, it implements the <code>ResteasyWadlDefaultResource</code>
            and serves this URL by default:</para>
        <programlisting><![CDATA[/application.xml]]></programlisting>
        <para>To enable the GRAMMAR generation, extend the <code>ResteasyWadlDefaultResource</code> like this:</para>
        <programlisting><![CDATA[import org.jboss.resteasy.wadl.ResteasyWadlDefaultResource;
import org.jboss.resteasy.wadl.ResteasyWadlWriter;

import jakarta.ws.rs.Path;

@Path("/")
public class MyWadlResource extends ResteasyWadlDefaultResource {

    public MyWadlResource() {
        ResteasyWadlWriter.ResteasyWadlGrammar wadlGrammar = new ResteasyWadlWriter.ResteasyWadlGrammar();
        wadlGrammar.enableSchemaGeneration();
        getWadlWriter().setWadlGrammar(wadlGrammar);

    }
}]]></programlisting>
        <para>With the above setup, the WADL module will generate GRAMMAR automatically and register the service under this url:</para>
        <programlisting><![CDATA[/wadl-extended/xsd0.xsd]]></programlisting>
        <para>Above is the basic usage of the WADL module under a servlet container deployment.</para>
    </section>
    <section>
        <title>RESTEasy WADL support for Sun JDK HTTP Server</title>
        <para>
            RESTEasy provides a ResteasyWadlDefaultResource to generate WADL info for its embedded
            containers. Here is an example to show how to use it with RESTEasy's Sun JDK HTTP Server container:
        </para>
        <programlisting><![CDATA[com.sun.net.httpserver.HttpServer httpServer =
	com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(port), 10);

org.jboss.resteasy.plugins.server.sun.http.HttpContextBuilder contextBuilder = 
	new org.jboss.resteasy.plugins.server.sun.http.HttpContextBuilder();

contextBuilder.getDeployment().getActualResourceClasses()
	.add(ResteasyWadlDefaultResource.class);
contextBuilder.bind(httpServer);

ResteasyWadlDefaultResource.getServices()
	.put("/",
		ResteasyWadlGenerator
			.generateServiceRegistry(contextBuilder.getDeployment()));

httpServer.start();]]></programlisting>
        <para>
            From the above code example, we can see how ResteasyWadlDefaultResource is registered
            in the deployment:
        </para>
        <programlisting><![CDATA[contextBuilder.getDeployment().getActualResourceClasses()
	.add(ResteasyWadlDefaultResource.class);]]></programlisting>
        <para>
            Another important task is to use ResteasyWadlGenerator to generate the WADL info for the
            resources in the deployment:
        </para>
        <programlisting><![CDATA[ResteasyWadlDefaultResource.getServices()
	.put("/",
		ResteasyWadlGenerator
			.generateServiceRegistry(contextBuilder.getDeployment()));]]></programlisting>
        <para>After the above configuration is set, users can access "/application.xml" to fetch the
            WADL info, because ResteasyWadlDefaultResource has @PATH set to "/application.xml" as default:
        </para>
        <programlisting><![CDATA[@Path("/application.xml")
public class ResteasyWadlDefaultResource]]></programlisting>
    </section>
    <section>
        <title>RESTEasy WADL support for Netty Container</title>
        <para>RESTEasy WADL support for Netty Container is similar to the support for JDK HTTP Server.
            It uses ResteasyWadlDefaultResource to serve '/application.xml' and ResteasyWadlGenerator
            to generate WADL info for resources. Here is the sample code:
        </para>
        <programlisting><![CDATA[ResteasyDeployment deployment = new ResteasyDeploymentImpl();

netty = new NettyJaxrsServer();
netty.setDeployment(deployment);
netty.setPort(port);
netty.setRootResourcePath("");
netty.setSecurityDomain(null);
netty.start();

deployment.getRegistry()
	.addPerRequestResource(ResteasyWadlDefaultResource.class);        
ResteasyWadlDefaultResource.getServices()
	.put("/", ResteasyWadlGenerator.generateServiceRegistry(deployment));]]></programlisting>
        <para>
            Please note for all embedded containers like JDK HTTP Server and Netty Container, if the
            resources in the deployment changes at runtime, the ResteasyWadlGenerator.generateServiceRegistry()
            needs to be re-run to refresh the WADL info.
        </para>
    </section>
    <section>
        <title>RESTEasy WADL Support for Undertow Container</title>
        <para>
            The RESTEasy Undertow Container is an embedded Servlet Container, and RESTEasy WADL provides
            a connector to it. To use RESTEasy Undertow Container together with WADL support,
            add these three components into project maven dependencies:
        </para>
        <programlisting><![CDATA[
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-wadl</artifactId>
	<version>${project.version}</version>
</dependency>
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-wadl-undertow-connector</artifactId>
	<version>${project.version}</version>
</dependency>
<dependency>
	<groupId>org.jboss.resteasy</groupId>
	<artifactId>resteasy-undertow</artifactId>
	<version>${project.version}</version>
</dependency>
]]></programlisting>
        <para>The resteasy-wadl-undertow-connector provides a WadlUndertowConnector to help use
            WADL in RESTEasy Undertow Container. Here is the code example:
        </para>
        <programlisting><![CDATA[
UndertowJaxrsServer server = new UndertowJaxrsServer().start();
WadlUndertowConnector connector = new WadlUndertowConnector();
connector.deployToServer(server, MyApp.class);
]]></programlisting>
        <para>The MyApp class shown in above code is a standard &REST-API; Application class in your project:</para>
        <programlisting>
            <![CDATA[
@ApplicationPath("/base")
public static class MyApp extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        HashSet<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(YourResource.class);
        return classes;
    }
}
]]></programlisting>
        <para>After the Application is deployed to the UndertowJaxrsServer via WadlUndertowConnector,
            the user can access the WADL info at "/application.xml" prefixed by the @ApplicationPath in the
            Application class. To override the @ApplicationPath, use the other method
            in WadlUndertowConnector:</para>
        <programlisting>
            <![CDATA[
public UndertowJaxrsServer deployToServer(UndertowJaxrsServer server, Class<? extends Application> application, String contextPath)
            ]]>
        </programlisting>
        <para>The "deployToServer" method shown above accepts a "contextPath" parameter, which can be used
            to override the @ApplicationPath value in the Application class.</para>
    </section>
</chapter>
