users@jersey.java.net

Re: [Jersey] WadlGenerator does not generate resource methods for subresources?

From: Marc Hadley <Marc.Hadley_at_Sun.COM>
Date: Wed, 11 Jun 2008 16:10:53 -0400

Here's a patch for the trunk version of WadlGenerator that adds the
methods for resources accessed via sub-resource locators. I also
attach the WADL generated for the SimpleConsole sample application
which uses a sub resource locator for the Colours resource class.

One issue that occurred to me is how to handle circular references,
e.g. a resource class that has a subresource locator that returns an
instance of itself could generate an infinitely nested WADL. For now
I've protected against this with a simple list of visited classes but
this could be improved upon by generating a top level resource_type
element for each resource class and referring to that from each
resource element. With this a client could infer the circular
relationship which isn't possible with the current solution which just
includes a bare resource element for previously visited resource
classes. The downside is that the WADL would become more verbose.

Marc.

# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /Users/mh124079/Development/
Java/jersey/jersey/src/impl/com/sun/jersey/impl/wadl
# This patch can be applied using context Tools: Patch action on
respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: WadlGenerator.java
--- WadlGenerator.java Base (BASE)
+++ WadlGenerator.java Locally Modified (Based On LOCAL)
@@ -50,7 +50,9 @@
  import com.sun.jersey.api.model.AbstractSubResourceLocator;
  import com.sun.jersey.api.model.AbstractSubResourceMethod;
  import com.sun.jersey.api.model.Parameter;
+import com.sun.jersey.impl.modelapi.annotation.IntrospectionModeller;
  import java.util.HashMap;
+import java.util.HashSet;
  import java.util.Map;
  import java.util.Set;
  import javax.ws.rs.core.MediaType;
@@ -71,10 +73,11 @@
      public static Application generate(Set<AbstractResource>
resources) {
          Application wadlApplication = new Application();
          Resources wadlResources = new Resources();
+ Set<Class<?>> visitedClasses = new HashSet<Class<?>>();

          // for each resource
          for (AbstractResource r: resources) {
- Resource wadlResource = generateResource(r);
+ Resource wadlResource = generateResource(r, null,
visitedClasses);
              wadlResources.getResource().add(wadlResource);
          }
          wadlApplication.setResources(wadlResources);
@@ -89,7 +92,8 @@
      public static Application generate(AbstractResource resource) {
          Application wadlApplication = new Application();
          Resources wadlResources = new Resources();
- Resource wadlResource = generateResource(resource);
+ Set<Class<?>> visitedClasses = new HashSet<Class<?>>();
+ Resource wadlResource = generateResource(resource, null,
visitedClasses);
          wadlResources.getResource().add(wadlResource);
          wadlApplication.setResources(wadlResources);
          return wadlApplication;
@@ -203,11 +207,19 @@
          return wadlParam;
      }

- private static Resource generateResource(AbstractResource r) {
+ private static Resource generateResource(AbstractResource r,
String path, Set<Class<?>> visitedClasses) {
          Resource wadlResource = new Resource();
- if (r.isRootResource())
+ if (path != null)
+ wadlResource.setPath(path);
+ else if (r.isRootResource())
              wadlResource.setPath(r.getUriPath().getValue());

+ // prevent infinite recursion
+ if (visitedClasses.contains(r.getResourceClass()))
+ return wadlResource;
+ else
+ visitedClasses.add(r.getResourceClass());
+
          // for each resource method
          Map<String, Param> wadlResourceParams = new HashMap<String,
Param>();
          for (AbstractResourceMethod m : r.getResourceMethods()) {
@@ -251,12 +263,8 @@

          // for each sub resource locator
          for (AbstractSubResourceLocator l :
r.getSubResourceLocators()) {
- Resource wadlSubResource = new Resource();
- wadlSubResource.setPath(l.getUriPath().getValue());
- for (Parameter p : l.getParameters()) {
- Param wadlParam = generateParam(p);
- wadlSubResource.getParam().add(wadlParam);
- }
+ AbstractResource subResource =
IntrospectionModeller.createResource( l.getMethod().getReturnType() );
+ Resource wadlSubResource = generateResource(subResource,
l.getUriPath().getValue(), visitedClasses);
              wadlResource.getMethodOrResource().add(wadlSubResource);
          }
          return wadlResource;


The generated WADL for the SimpleConsole sample.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<application xmlns="http://research.sun.com/wadl/2006/10">
        <resources base="http://localhost:9998/resources/">
                <resource path="/form">
                        <method name="GET">
                                <response>
                                        <representation mediaType="text/html" />
                                </response>
                        </method>
                        <method name="POST">
                                <request>
                                        <representation mediaType="application/x-www-form-urlencoded" />
                                </request>
                                <response>
                                        <representation mediaType="text/html" />
                                </response>
                        </method>
                        <resource path="colours">
                                <method name="GET">
                                        <request>
                                                <param xmlns:xs="http://www.w3.org/2001/XMLSchema"
type="xs:string" style="query" name="match" />
                                        </request>
                                        <response>
                                                <representation mediaType="text/plain" />
                                        </response>
                                </method>
                                <method name="GET">
                                        <request>
                                                <param xmlns:xs="http://www.w3.org/2001/XMLSchema"
type="xs:string" style="query" name="match" />
                                        </request>
                                        <response>
                                                <representation mediaType="application/json" />
                                        </response>
                                </method>
                        </resource>
                </resource>
        </resources>
</application>

---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.