Hi Thierry,

I've just tried it on 2.0-RC1.

Here is a jUnit test case.

SampleResource1 and SampleResource2 offer both plain text and HTML on 
GET, and for simplicity, only HTML on POST (but that's only determined 
by the method itself -- the problem is that it's not even called).

SampleResource1 uses @Post.
SampleResource2 uses @Post("html").

SampleResource3 disables content-type negotiation.


The results are that posting a x-www-form-urlencoded entity to 
SampleResource1 and SampleResource2 doesn't work (the @Post-annotated 
methods are not called). Sending it to SampleResource3 works (but of 
course, content-type negotiation doesn't.)


It just seems that the content negotiation feature affects both request 
and response types, and that the @Post annotation expect that type to be 
the same both ways. Is this by design, or is it a bug?


Best wishes,

Bruno.





import org.junit.*;
import org.restlet.*;
import org.restlet.data.*;
import org.restlet.representation.*;
import org.restlet.resource.*;
import org.restlet.routing.Router;
import static org.junit.Assert.*;

public class PostAnnotationTest {
        public final static String PLAINTEXT_TEST = "Hello World!";
        public final static String HTMLTEXT_TEST = "<html><body><h1>Hello 
World!</h1></body></html>";
        public final static String HTMLTEXT_FORM_TEST = "<html><body><h1>Hello 
%s!</h1></body></html>";
        public final static String PARAM_NAME = "name";

        public static abstract class AbstractSampleResource extends 
ServerResource {
                @Override
                protected void doInit() throws ResourceException {
                        super.doInit();
                        setNegotiated(true);
                        getVariants().add(new Variant(MediaType.TEXT_HTML));
                        getVariants().add(new Variant(MediaType.TEXT_PLAIN));
                }

                @Get("html")
                public Representation toHtml() {
                        return new StringRepresentation(HTMLTEXT_TEST, 
MediaType.TEXT_HTML);
                }

                @Get("txt")
                public Representation toText() {
                        return new StringRepresentation(PLAINTEXT_TEST,
                                        MediaType.TEXT_PLAIN);
                }
        }

        public static class SampleResource1 extends AbstractSampleResource {
                @Post
                public Representation acceptForm(Representation entity) {
                        if (entity
                                        .isCompatible(new 
Variant(MediaType.APPLICATION_WWW_FORM))) {
                                Form postForm = new Form(entity);
                                return new StringRepresentation(
                                                
String.format(HTMLTEXT_FORM_TEST, postForm
                                                                
.getFirstValue(PARAM_NAME)),
                                                MediaType.TEXT_HTML);
                        } else {
                                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                                return null;
                        }
                }
        }

        public static class SampleResource2 extends AbstractSampleResource {
                @Post("html")
                public Representation acceptForm(Representation entity) {
                        if (entity
                                        .isCompatible(new 
Variant(MediaType.APPLICATION_WWW_FORM))) {
                                Form postForm = new Form(entity);
                                return new StringRepresentation(
                                                
String.format(HTMLTEXT_FORM_TEST, postForm
                                                                
.getFirstValue(PARAM_NAME)),
                                                MediaType.TEXT_HTML);
                        } else {
                                setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
                                return null;
                        }
                }
        }

        public static class SampleResource3 extends SampleResource2 {
                @Override
                protected void doInit() throws ResourceException {
                        super.doInit();
                        setNegotiated(false);
                }
        }

        public static class SampleApplication extends Application {
                @Override
                public synchronized Restlet createInboundRoot() {
                        Router router = new Router(getContext());
                        router.attach("sr1", SampleResource1.class);
                        router.attach("sr2", SampleResource2.class);
                        router.attach("sr3", SampleResource3.class);
                        return router;
                }

        }

        int portnumber = 50000;
        Component component;

        @Before
        public void setUp() throws Exception {
                portnumber++;
                component = new Component();
                component.getServers().add(Protocol.HTTP, portnumber);
                component.getDefaultHost().attach("/", new SampleApplication());
                component.start();
        }

        @After
        public void tearDown() throws Exception {
                if (component != null) {
                        component.stop();
                }
        }

        @Test
        public void testSr1GetPlainText() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr1";, portnumber));
                testResource.get(MediaType.TEXT_PLAIN);
                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_PLAIN, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(PLAINTEXT_TEST, 
testResource.getResponse().getEntity()
                                .getText());
        }

        @Test
        public void testSr1GetHtml() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr1";, portnumber));
                testResource.get(MediaType.TEXT_HTML);
                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_HTML, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(HTMLTEXT_TEST, 
testResource.getResponse().getEntity()
                                .getText());
        }

        @Test
        public void testSr1PostFormHtml() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr1";, portnumber));

                Form postForm = new Form();
                postForm.add(PARAM_NAME, "World");

                testResource.post(postForm.getWebRepresentation(), 
MediaType.TEXT_HTML);

                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_HTML, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(HTMLTEXT_TEST, String.format(HTMLTEXT_FORM_TEST, 
postForm
                                .getFirstValue(PARAM_NAME)));
        }

        @Test
        public void testSr2GetPlainText() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr2";, portnumber));
                testResource.get(MediaType.TEXT_PLAIN);
                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_PLAIN, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(PLAINTEXT_TEST, 
testResource.getResponse().getEntity()
                                .getText());
        }

        @Test
        public void testSr2GetHtml() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr2";, portnumber));
                testResource.get(MediaType.TEXT_HTML);
                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_HTML, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(HTMLTEXT_TEST, 
testResource.getResponse().getEntity()
                                .getText());
        }

        @Test
        public void testSr2PostFormHtml() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr2";, portnumber));

                Form postForm = new Form();
                postForm.add(PARAM_NAME, "World");

                testResource.post(postForm.getWebRepresentation(), 
MediaType.TEXT_HTML);

                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_HTML, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(HTMLTEXT_TEST, String.format(HTMLTEXT_FORM_TEST, 
postForm
                                .getFirstValue(PARAM_NAME)));
        }

        @Test
        public void testSr3GetHtml() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr3";, portnumber));
                testResource.get(MediaType.TEXT_HTML);
                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_HTML, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(HTMLTEXT_TEST, 
testResource.getResponse().getEntity()
                                .getText());
        }

        @Test
        public void testSr3PostFormHtml() throws Exception {
                ClientResource testResource = new ClientResource(String.format(
                                "http://localhost:%d/sr3";, portnumber));

                Form postForm = new Form();
                postForm.add(PARAM_NAME, "World");

                testResource.post(postForm.getWebRepresentation(), 
MediaType.TEXT_HTML);

                assertTrue(testResource.getStatus().isSuccess());
                assertEquals(MediaType.TEXT_HTML, testResource.getResponse()
                                .getEntity().getMediaType());
                assertEquals(HTMLTEXT_TEST, String.format(HTMLTEXT_FORM_TEST, 
postForm
                                .getFirstValue(PARAM_NAME)));
        }
}






Thierry Boileau wrote:
> Hello Bruno,
> 
> what release of Restlet are you using? I think the 405 status has been 
> fixed recently.
> 
> Best regards,
> Thierry Boileau
> 
>> Hi,
>>
>>
>> Firstly, I'd like to write a ServerResource that uses @Get("xml") and 
>> @Get("html") for content negotiation on GET but not on POST (where it 
>> would return a different content-type depending on what the method does, 
>> or do the negotiation internally).
>> Secondly, I'd like to be able to post some 
>> "application/x-www-form-urlencoded" content and get another type in return.
>>
>>
>> public class MyResource extends
>>              ServerResource {
>>      @Override
>>      protected void doInit() throws ResourceException {
>>              super.doInit();
>>              setNegotiated(true);
>>              getVariants().add(new Variant(MediaType.TEXT_HTML));
>>              getVariants().add(new Variant(MediaType.APPLICATION_XHTML));
>>              getVariants().add(new Variant(MediaType.APPLICATION_RDF_XML));
>>      }
>>
>>      @Get("html")
>>      public Representation toHtml() throws ResourceException {
>>         ...
>>      }
>>
>>      @Get("xml")
>>      public Representation toXml() throws ResourceException {
>>             ...
>>      }
>>
>>      @Post
>>      public Representation accept(Representation entity) throws 
>> ResourceException {
>>             ...
>>      }
>> }
>>
>>
>> At the moment, if I turn off the content-type negotiation 
>> (setNegotiated(false)), then 'accept' is being called up receiving a 
>> POST request. If content-negotiation is on (setNegotiated(true)), I get 
>> a 405 (method not allowed) error.
>> It looks like this is due to the logic in doNegotiatedHandle(), which 
>> I'd rather not override.
>>
>>
>> I'm not entirely sure it's because of the content-type negotiation on 
>> the returned type, but it might be due to the input type too. (Hence the 
>> second part of this problem.)
>>
>> I've tried this      @Post("html"), @Post("xml") and @Post("html|xml"), but 
>> they're never called anyway, so it doesn't seem to have much to do with 
>> the negotiated return type (the browser accepts "*/*" by the way).
>>
>> What's posted is of type "application/x-www-form-urlencoded". It looks 
>> like the @Post annotation make the negotiation on the input type too.
>> If I tweak client to send the same content as "text/html", the 
>> @Post("html") is called. This seems a bit wrong (posting 
>> x-www-form-urlencoded forms and getting HTML in return seems quite 
>> common, and that doesn't seem feasible if content-type negotiation is on).
>> Did I miss something? Any workarounds?
>>
>>
>> Best wishes,
>>
>> Bruno.
>>
>> ------------------------------------------------------
>> http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2460162
>>
>>

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=2460607

Reply via email to