Hi Gabo
Hi Team,
Sorry this would be a bit lengthy. Just want to put everything needed to debug this available. I would summarize the issue later
in the end of the post.
No problems. will just do some snips...
I have the following class declaration:
@WebService(name="MyService",
targetNamespace="http://some.domain.com/")
@SOAPBinding(use=Use.LITERAL, style=Style.RPC)
@Consumes("text/xml")
@Produces("text/xml")
@Path("/MyService")
public interface MyService {
@GET
@Path("/")
@WebMethod
@WebResult(name="check")
public boolean check();
@GET
@Path("/")
@WebMethod
@WebResult(name="objectInstance")
public WSMyObject getMyObject(
@QueryParam("objectID")
@WebParam(name="objectID")
long objectID);
/*-
* This method intentionally has no HTTP Method annotation.
* This method will be used for sub-resource locator feature
* of JAX-RS.
*/
@Path("/")
@WebMethod(exclude=true)
public WSMyObject getMyObjectProperty(
@QueryParam("objectID")
long objectID
);
@PUT
@Path("/")
@WebMethod
@WebResult(name="objectID")
public long insertMyObject(
@WebParam(name="objectInstance")
@FormParam(value="objectInstance")
WSMyObject objectInstance,
@QueryParam("comment")
@WebParam(name="comment")
String comment
);
@POST
@Path("/")
@WebMethod
@WebResult(name="count")
public int updateMyObject(
@WebParam(name="objectInstance")
@FormParam(value="objectInstance")
WSMyObject objectInstance,
@QueryParam("comment")
@WebParam(name="comment")
String comment
);
}
<snip/>
Generated WADL is as follows:
<resource path="/MyService">
<snip/>
<method name="POST">
<request>
<representation mediaType="text/xml">
<param name="objectInstance" style="query" />
<param name="comment" style="query" type="xs:string" />
</representation>
</request>
<response>
<!-- Primitive type : xs:int -->
<representation mediaType="text/xml" />
</response>
</method>
</resource>
@FormParam refers to an individal pair in an application/www-url-encoded sequence, but not to a request body (the whole sequnce of
all the name/value pairs). I'm not sure about combining FormParam and QueryParam...Resource is said to consume text/xml...but the
presense of FormParam assumes it is an application/www-url-encoded request....
Also, I can see
<!-- Primitive type : xs:int -->
<representation mediaType="text/xml" />
it is confusing though given that you have @Produces(text/xml), it can be explained, perhaps one have a provbider converting
primitives into simple xml sequences. May be it is worth overriding it on a method and set @Produces("text/plain")
If I remove @FormParam the annotation the WADL gets adjusted as follows:
<method name="POST">
<request>
<representation mediaType="text/xml">
<representation mediaType="text/xml" element="prefix1:MyObject"/>
<param name="comment" style="query" type="xs:string" />
</representation>
</request>
<response>
Issue #1: Why is the style set to query with the @FormParam annotation? Shouldn't it be of type request or body? Basing my
thoughts from http://jackson.codehaus.org/javadoc/jax-rs/1.0/javax/ws/rs/FormParam.html
I'm pretty sure I asked the question on the WADL list and was advised to set the style to 'query' if it is
application/www-url-encoded...
Another thing is that you have 2 representation elements, this is because after you removed @FormParam you have a method woth two
parameters without being annotated with JAXRS param annotations. Perhaps CXF JAXRS server should just fail to initialize the
resource object in this case as it is against the JAXRS spec rule prohibiting such methods.
----
I try to invoke updateMyObject with the following xml as payload:
POST /some/path/MyService?comment=test HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.1
Content-Length: 2979
Content-Type: application/xml; charset=ISO-8859-1
Host: localhost:8080
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectInstance xmlns="http://some.domain.com">
<objectID>2589</objectID>
<!-- other fields go here -->
</objectInstance>
Issue #2: The method being invoked is check(). It seems there is some failure with regards to unmarshalling of the payload and it
defaults to GET?
Is it really the case ? Are you sure POST is on the wire ? Is it possible that
you have some handler replacing POST with GET ?
Issue #3: I removed check(). The method being picked up now is getMyObjectProperty() even if the queryParameter objectID is not
present.
It does not matter if a query parameter is present or not. It is the HTTP method, content type, accept types and URI which affect
the selection. getMyObject inherits @Produces from the class. and for the reason a POST annotated method is not invoked given that
you have an "application/xml" ContentType but the code restricts the Consumes types to text/xml only. So getMyObjectProperty()
subresource locator is given a chance. By the wau, check() and getMyObject() are absolutely equal candidates, nothing distinguishes
between the two, as far as the selection is concerned, getCheck() will be invoked first because it is just happens to be the first
matching one...
I try to invoke insertMyObject with the following xml as payload:
PUT /some/path/MyService?comment=test HTTP/1.1
User-Agent: Jakarta Commons-HttpClient/3.1
Content-Length: 2979
Content-Type: application/xml; charset=ISO-8859-1
Host: localhost:8080
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<objectInstance xmlns="http://some.domain.com">
<objectID>2589</objectID>
<!-- other fields go here -->
</objectInstance>
Issue #4: I am expecting a 401 challenge with Digest as authentication. I have an interceptor for this. I am 100% sure that the
word "basic" never occurs in the code, but I get this:
HTTP/1.1 401 Unauthorized
Server: Sun-ONE-Web-Server/6.1
Date: Fri, 22 Jan 2010 10:02:28 GMT
Content-length: 223
Content-type: text/html
WWW-authenticate: Basic realm="Sun ONE Web Server"
I am using iPlanet as server. It seems something else is processing the
transaction, although I cannot pinpoint yet which.
Probably something to do with the iPlanet rejecting it, CXF JAXRS does not do
the checks itself
Issue #5: Reordering the parameters does not affect the behavior for #2-4. Removing the comment parameter does not affect
behavior.
Parameters do not affect the way methods are chosen.
Issue #6: Removing getMyObjectProperty() shows that the request is not mapped
properly. I get the following exception:
this is because you have application/xml but not text/xml - expand Consumes a
bit....
So far the only issue which I'm concerned about is the fact that you say GET annotated check() is invoked when you do POST, can you
please give me more info ?
javax.ws.rs.WebApplicationException
at
org.apache.cxf.jaxrs.utils.JAXRSUtils.findTargetMethod(JAXRSUtils.java:375)
at
org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.processRequest(JAXRSInInterceptor.java:179)
at
org.apache.cxf.jaxrs.interceptor.JAXRSInInterceptor.handleMessage(JAXRSInInterceptor.java:63)
I could be missing something simple. I just find it odd during my initial testing the part where there is just the complex object
as parameter, this worked. From there, I added the Digest interceptor and the second paramter. Now, removing both and I still get
the exception. It is also a bit disturbing why the POST as posted above goes to other methods which were explicitly stated to map
only to GET.
Indeed, it must not happen. Can you please double-check everything ?
cheers, Sergey
Please advise if there are other info that is needed. Thanks in advance.
Gabo