Hi All

Colm found out few weeks back that a Syncope REST service WADL can not be generated back into the Java code with a CXF wadl-to-java plugin. Here is the original info Colm helped with:

A ResourceService has two "list" methods:

    @GET
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    List<ResourceTO> list();

    @GET
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
List<ResourceTO> list(@NotNull @MatrixParam("connectorId") Long connInstanceId);

This is represented in WADL like this: (I've removed <doc> and some other mark up. like extra representations, etc):

<resource path="/resources">
  <param name="connectorId" style="matrix" type="xs:long"/>
  <method name="GET">
     <response>
<representation mediaType="application/xml" element="syncope1:resources"/>
     </response>
  </method>
  <method name="GET">
     <response>
<representation mediaType="application/xml" element="syncope1:resources"/>
     </response>
  </method>
</resource>

here is a relevant generated Java code:

    @GET
    @Produces({"application/xml", "application/json" })
    Resources list(@MatrixParam("connectorId") Long connectorId);

    @GET
    @Produces({"application/xml", "application/json" })
    Resources list(@MatrixParam("connectorId") Long connectorId);

which fails to compile.


The issue stems from the fact the 2 original GET methods depend on a custom selection algorithm (the optional parameters like MatrixParam) do not affect the JAX-RS selection algorithm process, hence by default those 2 methods are equal candidates so an extension is used to make the selection predictable.

next, WADL requires that the path segment parameters (PathParam or MatrixParam) are represented as the immediate wadl:resource children as the generated WADL fragment shows.

Thus a WADL to Java generation has no idea that one of the two list methods needs to have a MatrixParam in its signature, the other does not.

There are two ways to fix it.

1. simply collapse the original two methods into one and check if MatrixParam is null inside the method:

    @GET
    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
    List<ResourceTO> list(@MatrixParam("connectorId") Long connInstanceId);


The requests with or without this Matrixparam will be routed to this method. The only side-effect: the client proxies which do list() would need to do list(null).

2. I've added a new WADLGenerator property in CXF 3.0.3, "ignoreOverloadedMethods". If it is set then you'd just get:

<resource path="/resources">
  <param name="connectorId" style="matrix" type="xs:long"/>
  <method name="GET">
     <response>
<representation mediaType="application/xml" element="syncope1:resources"/>
     </response>
  </method>
</resource>

which is correct. We can tune the generator further to have
<param name="connectorId" style="matrix" type="xs:long" required="false"/>

but matrix parameters are optional by the definition.


Finally, not an issue but a praise for a WADL stylesheet shipped with Syncope. I saw a recent presentation from Colm, and I thought, wow, would it be great if CXF WADLGenerator could optionally reference such a stylesheet via an XML processing instruction. In fact I've even updated the generator to do it if it is configured with a reference to
a class path resource.
We've done in CXF some work for the optional Swagger integration and Andriy Redko even did a demo. I think one of the reasons Swagger is so popular because people can get UI auto-generated out of it.

Would it possible to get this style-sheet shipped in a self-contained module? CXF users who need would add it to a classpath and then configure CXF WADLGenerator with a class path reference to it...

Cheers, Sergey



Reply via email to