Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my method in jersey get called twice?

I have HomeService.java and when I go to the /test url it prints HomeService::test once, but when I go to the /play url it prints HomeService::play twice. How can I get my /play method to only be called once?

The urls I go to are

http://127.0.0.1:8080/Home/rest/main/test
http://127.0.0.1:8080/Home/rest/main/play

HomeService.java:

@Path("/main")
public class HomeService
{

  @GET
  @Path("/test")
  @Produces("text/plain")
  public String test()
  {
    System.out.println("HomeService::test");
    return "Running...";
  }

  @GET
  @Path("/play")
  @Produces("video/mpeg")
  public StreamingOutput play()
  {
    System.out.println("HomeService::play");
    return new StreamingOutput()
    {

    @Override
    public void write(java.io.OutputStream outputStream) {}
  }
}

Web.xml

<?xml version="1.0" encoding="UTF-8"?><web-app id="WebApp_ID" version="2.4"
    xmlns="http://java.sun.com/xml/ns/j2ee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
  <display-name>Home</display-name>

    <servlet>
        <servlet-name>jersey-servlet</servlet-name>
        <servlet-class>
                      com.sun.jersey.spi.container.servlet.ServletContainer
        </servlet-class>
        <init-param>
            <param-name>com.sun.jersey.config.property.packages</param-name>
            <param-value>com.home</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>

</web-app>

If more information is need let me know.

Edit: So I ran tcpdump and this was the output:

# ./tcpdump -s 128 -A -v -i any port 8080|grep 'play'
tcpdump: listening on any, link-type LINUX_SLL (Linux cooked), capture size 128 bytes
...u...uGET /Home/rest/main/play HTTP/1.1
..  ... .GET /Home/rest/main/play HTTP/1.1

and then again

........GET /Home/rest/main/play HTTP/1.1
........GET /Home/rest/main/play HTTP/1.1
like image 207
Grammin Avatar asked Nov 26 '25 19:11

Grammin


1 Answers

It's because the client requested it twice. You may expect this behavior on media (audio/video) requests. Most media players would test if the server supports range requests, so that it could be more efficiently buffered via multiple HTTP connections. If you look closer at the request headers, you may see Range and If-Range headers. If your server had supported it, then the client would send multiple range requests requesting smaller chunks of the media file starting and ending at the specified range. Also, if the client fast-forwards to a specific moment (e.g. 1 minute later), then the media player could just abort the request and send a new request requesting the range starting at exactly that position.

You can't stop clients from requesting it multiple times. If your service doesn't support range requests, you'd probably better make it one. The servletcontainer's builtin default servlet supports it. So if you put the media file in public web content and let the client request it directly instead of via a web service, then it'll worry about that.

Note that this problem is completely unrelated to Jersey, although I have somewhat the impression that it's the wrong tool for the particular job of media streaming.

like image 82
BalusC Avatar answered Nov 28 '25 09:11

BalusC