users@jersey.java.net

Re: [Jersey] HTTP DELETE method

From: Paul Sandoz <Paul.Sandoz_at_Sun.COM>
Date: Tue, 13 Apr 2010 18:01:22 +0200

Hi,

So basically when DELETE is used no request entity is sent?

Is the Client out-bound request for DELETE being logged? i guess not,
which is odd.

I notice you are using the InMemoryTestContainerFactory but yet
communicating with Tomcat? The InMemoryTestContainerFactory is
designed to deploy and work in memory without a network connection. I
think what you mean to use is the ExternalTestContainerFactory?

If you can send me a reproducible test case (privately if you like if
disclosure is an issue) and i can have a closer look.

Paul.

On Apr 13, 2010, at 5:35 PM, Jonathan Hodges wrote:

> Hi Paul,
>
> I agree that the method should have no bearing on the error, but
> unfortunately I am a bit of a loss on this one. I have turned on
> client and server side logging. I will show the request/response
> of the same Java method only changing the annotation from a PUT to
> DELETE.
>
> Here is the PUT
>
> Apr 13, 2010 9:02:39 AM
> com
> .sun
> .jersey
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory
> $InMemoryTestContainer <init>
> INFO: Creating low level InMemory test container configured at the
> base URI http://localhost:9998/
> Apr 13, 2010 9:02:39 AM
> com
> .sun
> .jersey
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory
> $InMemoryTestContainer start
> INFO: Starting low level InMemory test container
> Apr 13, 2010 9:02:39 AM
> com.sun.jersey.server.impl.application.WebApplicationImpl initiate
> INFO: Initiating Jersey application, version 'Jersey: 1.1.5.1
> 03/10/2010 02:33 PM'
> Apr 13, 2010 9:02:40 AM
> com.sun.jersey.api.client.filter.LoggingFilter log
> INFO: 1 * Client out-bound request
> 1 > PUT http://64.210.194.198:8080/useractivity/rest/removeUserSocialIdentity
> 1 > Content-Type: application/json
> 1 > Accept: text/plain
> 1 > Version: 1.0
> 1 >
> {"userSocialIdentity":[{"socialIdentityList":{"socialIdentity":
> [{"typeCode":"TWITTER","uid":"c1c5c6f8030377730010d4482c0f5d03"},
> {"typeCode":"MYSPACE","uid":"a1c5c6f8030377730010d4482c0f5d03"},
> {"typeCode":"FACEBOOK","uid":"f1c5c6f8030377730010d4482c0f5d03"}]},"userUID":"b5c587fe030377730010d4482d6148ea"},{"socialIdentityList":{"socialIdentity":[{"typeCode":"MYSPACE","uid":"a1c5c6f8030377730010d4482c0f5d03"},{"typeCode":"TWITTER","uid":"c1c5c6f8030377730010d4482c0f5d03"},{"typeCode":"FACEBOOK","uid":"f1c5c6f8030377730010d4482c0f5d03"}]},"userUID":"b5c587fe030377730010d4482d6148ea"}]}
>
> Apr 13, 2010 9:02:40 AM
> com.sun.jersey.api.client.filter.LoggingFilter log
> INFO: 1 * Client in-bound response
> 1 < 200
> 1 < Server: Apache-Coyote/1.1
> 1 < Content-Type: text/plain
> 1 < Content-Length: 2
> 1 < Date: Tue, 13 Apr 2010 15:03:47 GMT
> 1 <
> OK
>
> It works as expected. Now here's the DELETE.
>
> Apr 13, 2010 9:30:39 AM
> com
> .sun
> .jersey
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory
> $InMemoryTestContainer <init>
> INFO: Creating low level InMemory test container configured at the
> base URI http://localhost:9998/
> Apr 13, 2010 9:30:39 AM
> com
> .sun
> .jersey
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory
> $InMemoryTestContainer start
> INFO: Starting low level InMemory test container
> Apr 13, 2010 9:30:39 AM
> com.sun.jersey.server.impl.application.WebApplicationImpl initiate
> INFO: Initiating Jersey application, version 'Jersey: 1.1.5.1
> 03/10/2010 02:33 PM'
> Apr 13, 2010 9:30:40 AM
> com.sun.jersey.api.client.filter.LoggingFilter log
> INFO: 1 * Client in-bound response
> 1 < 500
> 1 < Server: Apache-Coyote/1.1
> 1 < Content-Type: text/html;charset=utf-8
> 1 < Content-Length: 3739
> 1 < Date: Tue, 13 Apr 2010 15:31:47 GMT
> 1 < Connection: close
> 1 <
> <html><head><title>Apache Tomcat/6.0.16 - Error report</
> title><style><!--H1 {font-family:Tahoma,Arial,sans-
> serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-
> family:Tahoma,Arial,sans-serif;color:white;background-
> color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-
> serif;color:white;background-color:#525D76;font-size:14px;} BODY
> {font-family:Tahoma,Arial,sans-serif;color:black;background-
> color:white;} B {font-family:Tahoma,Arial,sans-
> serif;color:white;background-color:#525D76;} P {font-
> family:Tahoma,Arial,sans-serif;background:white;color:black;font-
> size:12px;}A {color : black;}A.name {color : black;}HR {color :
> #525D76;}--></style> </head><body><h1>HTTP Status 500 - </h1><HR
> size="1" noshade="noshade"><p><b>type</b> Exception report</
> p><p><b>message</b> <u></u></p><p><b>description</b> <u>The server
> encountered an internal error () that prevented it from fulfilling
> this request.</u></p><p><b>exception</b>
> <pre>java.lang.IllegalStateException: reader must be on a
> START_ELEMENT event, not a 8 event
>
> com
> .sun
> .xml
> .bind
> .v2
> .runtime
> .unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:352)
>
> com
> .sun
> .xml
> .bind
> .v2
> .runtime
> .unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
>
> com
> .sun
> .jersey
> .json
> .impl
> .BaseJSONUnmarshaller
> .unmarshalJAXBElementFromJSON(BaseJSONUnmarshaller.java:103)
>
> com
> .sun
> .jersey
> .json
> .impl
> .BaseJSONUnmarshaller.unmarshalFromJSON(BaseJSONUnmarshaller.java:92)
>
> com
> .sun
> .jersey
> .json
> .impl
> .provider
> .entity
> .JSONRootElementProvider.readFrom(JSONRootElementProvider.java:100)
>
> com
> .sun
> .jersey
> .core
> .provider
> .jaxb
> .AbstractRootElementProvider
> .readFrom(AbstractRootElementProvider.java:105)
>
> com
> .sun
> .jersey
> .spi.container.ContainerRequest.getEntity(ContainerRequest.java:444)
>
> com
> .sun
> .jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider
> $EntityInjectable.getValue(EntityParamDispatchProvider.java:137)
>
> com
> .sun
> .jersey
> .server
> .impl
> .inject
> .InjectableValuesProvider
> .getInjectableValues(InjectableValuesProvider.java:43)
>
> com
> .sun
> .jersey
> .server
> .impl.model.method.dispatch.AbstractResourceMethodDispatchProvider
> $
> EntityParamInInvoker
> .getParams(AbstractResourceMethodDispatchProvider.java:119)
>
> com
> .sun
> .jersey
> .server
> .impl.model.method.dispatch.AbstractResourceMethodDispatchProvider
> $
> TypeOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:
> 147)
>
> com
> .sun
> .jersey
> .server
> .impl
> .model
> .method
> .dispatch
> .ResourceJavaMethodDispatcher
> .dispatch(ResourceJavaMethodDispatcher.java:67)
>
> com
> .sun
> .jersey
> .server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:259)
>
> com
> .sun
> .jersey
> .server
> .impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
>
> com
> .sun
> .jersey
> .server
> .impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83)
>
> com
> .sun
> .jersey
> .server
> .impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
>
> com
> .sun
> .jersey
> .server
> .impl
> .uri
> .rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:71)
>
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl._handleRequest(WebApplicationImpl.java:990)
>
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl.handleRequest(WebApplicationImpl.java:941)
>
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl.handleRequest(WebApplicationImpl.java:932)
>
> com
> .sun
> .jersey.spi.container.servlet.WebComponent.service(WebComponent.java:
> 384)
>
> com
> .sun
> .jersey
> .spi
> .container.servlet.ServletContainer.service(ServletContainer.java:451)
>
> com
> .sun
> .jersey
> .spi
> .container.servlet.ServletContainer.service(ServletContainer.java:632)
> javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
> </pre></p><p><b>note</b> <u>The full stack trace of the root cause
> is available in the Apache Tomcat/6.0.16 logs.</u></p><HR size="1"
> noshade="noshade"><h3>Apache Tomcat/6.0.16</h3></body></html>
>
>
> I also looked in the headers and it looks like the client never
> sends the JSON payload with a DELETE which in turn causes the JAXB
> exception on the server. When I look at a PUT request I see the
> JSON payload in the request. I tried changing the payload to XML
> and I still see no payload, but I get a different error on the
> server HTTP 400 - bad request as can be seen below.
>
> Apr 13, 2010 9:33:28 AM
> com
> .sun
> .jersey
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory
> $InMemoryTestContainer <init>
> INFO: Creating low level InMemory test container configured at the
> base URI http://localhost:9998/
> Apr 13, 2010 9:33:28 AM
> com
> .sun
> .jersey
> .test.framework.spi.container.inmemory.InMemoryTestContainerFactory
> $InMemoryTestContainer start
> INFO: Starting low level InMemory test container
> Apr 13, 2010 9:33:28 AM
> com.sun.jersey.server.impl.application.WebApplicationImpl initiate
> INFO: Initiating Jersey application, version 'Jersey: 1.1.5.1
> 03/10/2010 02:33 PM'
> Apr 13, 2010 9:33:29 AM
> com.sun.jersey.api.client.filter.LoggingFilter log
> INFO: 1 * Client in-bound response
> 1 < 400
> 1 < Server: Apache-Coyote/1.1
> 1 < Content-Type: text/html;charset=utf-8
> 1 < Content-Length: 971
> 1 < Date: Tue, 13 Apr 2010 15:34:36 GMT
> 1 < Connection: close
> 1 <
> <html><head><title>Apache Tomcat/6.0.16 - Error report</
> title><style><!--H1 {font-family:Tahoma,Arial,sans-
> serif;color:white;background-color:#525D76;font-size:22px;} H2 {font-
> family:Tahoma,Arial,sans-serif;color:white;background-
> color:#525D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-
> serif;color:white;background-color:#525D76;font-size:14px;} BODY
> {font-family:Tahoma,Arial,sans-serif;color:black;background-
> color:white;} B {font-family:Tahoma,Arial,sans-
> serif;color:white;background-color:#525D76;} P {font-
> family:Tahoma,Arial,sans-serif;background:white;color:black;font-
> size:12px;}A {color : black;}A.name {color : black;}HR {color :
> #525D76;}--></style> </head><body><h1>HTTP Status 400 - </h1><HR
> size="1" noshade="noshade"><p><b>type</b> Status report</
> p><p><b>message</b> <u></u></p><p><b>description</b> <u>The request
> sent by the client was syntactically incorrect ().</u></p><HR
> size="1" noshade="noshade"><h3>Apache Tomcat/6.0.16</h3></body></html>
>
>
> Any ideas?
>
> -Jonathan
>
>
> On Tue, Apr 13, 2010 at 7:44 AM, Paul Sandoz <Paul.Sandoz_at_sun.com>
> wrote:
> Hi Jonathan,
>
> The stack trace appears to have nothing to do with the DELETE method
> and seems to be a problem with the parsing of the JSON request
> entity using the JSON JAXB support. I do not see how switching from
> @DELETE to @PUT would change anything in this respect.
>
> Note that there is a restriction in the HttpURLConnection
> implementation that for some crazy reason does not support DELETE
> when sending a request entity. And you rightly guess the Apache HTTP
> client does not have such a restriction.
>
> Can you enable client and server side logging.
>
> On the client side do:
>
> Client c = ...
> c.add(new LoggingFilter());
>
> and on the server side:
>
> https://jersey.dev.java.net/nonav/apidocs/latest/jersey/com/sun/jersey/api/container/filter/LoggingFilter.html
>
> as that might give some clues.
>
> Paul.
>
>
> On Apr 13, 2010, at 3:19 PM, Jonathan Hodges wrote:
>
> Hi,
>
> I am currently having trouble with getting the DELETE method to work
> correctly. This may be due to my misunderstanding of the semantics
> for DELETE so let me describe my scenario.
>
> I currently have a resource with the following code snipped deployed
> on Tomcat.
>
>
> @DELETE
> @Path("/removeUserSocialIdentity")
> @Consumes({MediaType.APPLICATION_XML,
> MediaType.APPLICATION_JSON})
> public String removeUserSocialIdentity(UserSocialIdentityList
> userSocialIdentityList) {
> logger.debug("removeUserSocialIdentity");
>
> return "OK";
> }
>
>
> I am trying to access this resource via the client API as follows.
>
>
> UserSocialIdentityList userSocialIdentityList = new
> UserSocialIdentityList();
> Set<UserSocialIdentity> userSocialIdentitySet = new
> HashSet<UserSocialIdentity>();
> UserSocialIdentity userSocialIdentity = new
> UserSocialIdentity();
>
> userSocialIdentity.setUserUID("b5c587fe030377730010d4482d6148ea");
>
> Set<SocialIdentity> socialIdentitySet = new
> HashSet<SocialIdentity>();
> SocialIdentityList socialIdentityList = new
> SocialIdentityList();
> SocialIdentity socialIdentity = new SocialIdentity();
> socialIdentity.setTypeCode("FACEBOOK");
>
> socialIdentity.setUid("f1c5c6f8030377730010d4482c0f5d03");
> socialIdentitySet.add(socialIdentity);
>
> socialIdentity = new SocialIdentity();
> socialIdentity.setTypeCode("TWITTER");
>
> socialIdentity.setUid("c1c5c6f8030377730010d4482c0f5d03");
> socialIdentitySet.add(socialIdentity);
>
> socialIdentity = new SocialIdentity();
> socialIdentity.setTypeCode("MYSPACE");
>
> socialIdentity.setUid("a1c5c6f8030377730010d4482c0f5d03");
> socialIdentitySet.add(socialIdentity);
>
>
> socialIdentityList.setSocialIdentitySet(socialIdentitySet);
>
> userSocialIdentity.setSocialIdentityList(socialIdentityList);
>
> userSocialIdentitySet.add(userSocialIdentity);
>
> userSocialIdentity = new UserSocialIdentity();
>
> userSocialIdentity.setUserUID("b5c587fe030377730010d4482d6148ea");
>
> socialIdentitySet = new HashSet<SocialIdentity>();
> socialIdentityList = new SocialIdentityList();
> socialIdentity = new SocialIdentity();
> socialIdentity.setTypeCode("FACEBOOK");
>
> socialIdentity.setUid("f1c5c6f8030377730010d4482c0f5d03");
> socialIdentitySet.add(socialIdentity);
>
> socialIdentity = new SocialIdentity();
> socialIdentity.setTypeCode("TWITTER");
>
> socialIdentity.setUid("c1c5c6f8030377730010d4482c0f5d03");
> socialIdentitySet.add(socialIdentity);
>
> socialIdentity = new SocialIdentity();
> socialIdentity.setTypeCode("MYSPACE");
>
> socialIdentity.setUid("a1c5c6f8030377730010d4482c0f5d03");
> socialIdentitySet.add(socialIdentity);
>
>
> socialIdentityList.setSocialIdentitySet(socialIdentitySet);
>
> userSocialIdentity.setSocialIdentityList(socialIdentityList);
>
> userSocialIdentitySet.add(userSocialIdentity);
>
>
> userSocialIdentityList.setUserSocialIdentity(userSocialIdentitySet);
>
> String response =
> wr.path("removeUserSocialIdentity")
> .type(MediaType.APPLICATION_JSON_TYPE)
> .accept(MediaType.TEXT_PLAIN)
> .header("Version", "1.0")
> .put(String.class,
> userSocialIdentityList);
>
> assertTrue("Method: removeUserSocialIdentity
> \nMessage: Something wrong, the returned " +
> "response is not 'OK'", response.equals("OK"));
>
>
> This yields the following exception.
>
>
> java.lang.IllegalStateException: reader must be on a START_ELEMENT
> event, not a 8 event
> at
> com
> .sun
> .xml
> .bind
> .v2
> .runtime
> .unmarshaller.UnmarshallerImpl.unmarshal0(UnmarshallerImpl.java:352)
> at
> com
> .sun
> .xml
> .bind
> .v2
> .runtime
> .unmarshaller.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:339)
> at
> com
> .sun
> .jersey
> .json
> .impl
> .BaseJSONUnmarshaller
> .unmarshalJAXBElementFromJSON(BaseJSONUnmarshaller.java:103)
> at
> com
> .sun
> .jersey
> .json
> .impl
> .BaseJSONUnmarshaller.unmarshalFromJSON(BaseJSONUnmarshaller.java:92)
> at
> com
> .sun
> .jersey
> .json
> .impl
> .provider
> .entity
> .JSONRootElementProvider.readFrom(JSONRootElementProvider.java:100)
> at
> com
> .sun
> .jersey
> .core
> .provider
> .jaxb
> .AbstractRootElementProvider
> .readFrom(AbstractRootElementProvider.java:105)
> at
> com
> .sun
> .jersey
> .spi.container.ContainerRequest.getEntity(ContainerRequest.java:444)
> at
> com
> .sun
> .jersey.server.impl.model.method.dispatch.EntityParamDispatchProvider
> $EntityInjectable.getValue(EntityParamDispatchProvider.java:137)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .inject
> .InjectableValuesProvider
> .getInjectableValues(InjectableValuesProvider.java:43)
> at
> com
> .sun
> .jersey
> .server
> .impl.model.method.dispatch.AbstractResourceMethodDispatchProvider
> $
> EntityParamInInvoker
> .getParams(AbstractResourceMethodDispatchProvider.java:119)
> at
> com
> .sun
> .jersey
> .server
> .impl.model.method.dispatch.AbstractResourceMethodDispatchProvider
> $
> VoidOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:
> 131)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .model
> .method
> .dispatch
> .ResourceJavaMethodDispatcher
> .dispatch(ResourceJavaMethodDispatcher.java:67)
> at
> com
> .sun
> .jersey
> .server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:259)
> at
> com
> .sun
> .jersey
> .server
> .impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
> at
> com
> .sun
> .jersey
> .server
> .impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:83)
> at
> com
> .sun
> .jersey
> .server
> .impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:133)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .uri
> .rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:71)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl._handleRequest(WebApplicationImpl.java:990)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl.handleRequest(WebApplicationImpl.java:941)
> at
> com
> .sun
> .jersey
> .server
> .impl
> .application
> .WebApplicationImpl.handleRequest(WebApplicationImpl.java:932)
> at
> com
> .sun
> .jersey.spi.container.servlet.WebComponent.service(WebComponent.java:
> 384)
> at
> com
> .sun
> .jersey
> .spi
> .container.servlet.ServletContainer.service(ServletContainer.java:451)
> at
> com
> .sun
> .jersey
> .spi
> .container.servlet.ServletContainer.service(ServletContainer.java:632)
> at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
> at
> org
> .apache
> .catalina
> .core
> .ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:
> 290)
> at
> org
> .apache
> .catalina
> .core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
> at
> org
> .apache
> .catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:
> 233)
> at
> org
> .apache
> .catalina.core.StandardContextValve.invoke(StandardContextValve.java:
> 191)
> at
> org
> .apache
> .catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
> at
> org
> .apache
> .catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
> at
> org
> .apache
> .catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:
> 109)
> at
> org
> .apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:
> 298)
> at
> org
> .apache.coyote.http11.Http11Processor.process(Http11Processor.java:
> 852)
> at org.apache.coyote.http11.Http11Protocol
> $Http11ConnectionHandler.process(Http11Protocol.java:588)
> at org.apache.tomcat.util.net.JIoEndpoint
> $Worker.run(JIoEndpoint.java:489)
> at java.lang.Thread.run(Thread.java:619)
>
>
>
> If I change the resource to accept PUT and change the client to make
> a PUT request instead of the DELETE it works perfectly. I already
> changed the client to use the Apache HTTP client so I can have a
> response with DELETE but I still can't seem to get past this issue.
> Any help would be greatly appreciated.
>
>
> Sincerely,
>
> Jonathan
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe_at_jersey.dev.java.net
> For additional commands, e-mail: users-help_at_jersey.dev.java.net
>
>