Zsolt Czinkos | 19 Aug 17:51

PUT problem with restlet client

Hello

I'd like to send HTTP 412 (precondition faild) status to client. It
works when I test it from curl (even if repeated a hundred times).
When I test is from a junit test using the restlet client, the test fails:

-------
java.lang.AssertionError: expected:<Precondition Failed (412) - The
precondition given in one or more of the request header fields
evaluated to false when it was tested on the server> but
was:<Communication Error (1001) - Software caused connection abort:
socket write error>
	at org.junit.Assert.fail(Assert.java:74)
	at org.junit.Assert.failNotEquals(Assert.java:448)
	at org.junit.Assert.assertEquals(Assert.java:102)
	at org.junit.Assert.assertEquals(Assert.java:117)
	at hu.zakk.atom.server.TestResourceTest.testPut(TestResourceTest.java:30)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
	at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
	at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
	at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
	at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
	at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
	at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
	at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
	at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
	at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
	at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
	at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
	at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
-----

According to the server log, everything is ok, 412 status sent:

2008.08.19. 17:43:44 com.noelios.restlet.LogFilter afterHandle
INFO: 2008-08-19	17:43:44	127.0.0.1	-	127.0.0.1	8182	PUT	/test/	-	412	391	-	0	http://localhost:8182	Noelios-Restlet-Engine/1.1.snapshot	-

When I use smaller file to test, it seems to work, but occasionally it
fails. If I increase the of the file above 64k, it seems to fail every
time.

See the java classes below. I use the restlet snapshot from maven repo
with jetty.

Probably a client issue?

Thanks

Zsolt

--------------------------------
The resource class:

package hu.zakk.test;

import java.util.List;
import java.util.logging.Logger;

import org.restlet.Context;
import org.restlet.data.MediaType;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.data.Tag;
import org.restlet.resource.Representation;
import org.restlet.resource.Resource;
import org.restlet.resource.ResourceException;
import org.restlet.resource.Variant;

public class TestResource extends Resource {

  private Logger log;

  public TestResource(Context context, Request request, Response response) {
    super(context, request, response);
    getVariants().add(new Variant(MediaType.ALL));
    log = getLogger();
  }

  @Override
  public void storeRepresentation(Representation entity)
      throws ResourceException {

      String tag = "fake";
      List<Tag> match = getRequest().getConditions().getMatch();
      Tag etag = match.isEmpty() ? null : match.get(0);
      if (etag == null || !etag.toString().equals(tag)) {
        log.info("precondition failed");
        getResponse().setStatus(Status.CLIENT_ERROR_PRECONDITION_FAILED);
        return;
      }
      log.info("NEVER HIT THIS");
  }

  @Override
  public boolean allowPut() {
    return true;
  }
}

-----------------------

The test:

package hu.zakk.test;

import static org.junit.Assert.assertEquals;

import java.io.ByteArrayInputStream;

import org.junit.Test;
import org.restlet.Client;
import org.restlet.data.MediaType;
import org.restlet.data.Protocol;
import org.restlet.data.Response;
import org.restlet.data.Status;
import org.restlet.resource.InputRepresentation;

public class TestResourceTest {

  @Test
  public void testPut() {
    // play with size
    int size = (int) Math.pow(2, 15) + 1;
    byte[] buf = new byte[size];
    for (int i = 0; i < size; i++) {
      buf[i] = 1;
    }

    ByteArrayInputStream bain = new ByteArrayInputStream(buf);

    Client client = new Client(Protocol.HTTP);
    Response putResponse = client.put("http://localhost:8182/test/",
        new InputRepresentation(bain, MediaType.TEXT_PLAIN));
    assertEquals(Status.CLIENT_ERROR_PRECONDITION_FAILED,
putResponse.getStatus());
  }

}


Gmane