0

I'm trying to build a remote service that will be called with Hessian (or any other remote call) but I'm facing problem with InputStreams. The Hessian web site says I'm better of dealing with them myself but I'm unable to figure how?

Below is a simple project using spring-boot to quickly launch a server and a simple client. The call to my remote service fails if the string passed is too long with the exception java.io.IOException: stream is close

Could any one help or point me to comprehensive documentation?

A simple service

public interface EchoService {InputStream echo(String text);}

The implementation

public class EchoServiceImpl implements EchoService {
  @Override
  public InputStream echo(String text) {
    System.out.println("Echo on server " + text);
    ByteArrayInputStream bis = new ByteArrayInputStream(text.getBytes());
    return bis;
  }
}

The server (using spring-boot)

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.remoting.caucho.HessianServiceExporter;
import org.springframework.remoting.support.RemoteExporter;

@Configuration @ComponentScan @EnableAutoConfiguration
public class Server {
    @Bean(name = "/repeat") 
    RemoteExporter bookingService() {
        HessianServiceExporter exporter = new HessianServiceExporter();
        exporter.setService(new EchoServiceImpl());
        exporter.setServiceInterface( EchoService.class );
        return exporter;
    }
    public static void main(String[] args) {
        SpringApplication.run(Server.class, args); 
    }
}

And the client

import com.caucho.hessian.client.HessianProxyFactory;
import com.google.common.io.ByteStreams;
public class Client {
    public static void main(String[] args) throws Exception {
        HessianProxyFactory factory = new HessianProxyFactory();
        EchoService service = (EchoService) factory.create(EchoService.class, "http://localhost:8080/repeat");
        try(InputStream is = service.echo(args[0])) {
            byte bis[] = ByteStreams.toByteArray(is);
            System.out.println(new String(bis));
        }
    }
}

The pom.xml if needed

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.4.3.RELEASE</version>
</parent>

<groupId>w.big.data</groupId>
<artifactId>hessian</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.report.sourceEncoding>UTF-8</project.report.sourceEncoding>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compilet.target>1.8</maven.compilet.target>
</properties>

<dependencies>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <version>18.0</version>
    </dependency>
    <dependency>
        <groupId>com.caucho</groupId>
        <artifactId>hessian</artifactId>
        <version>4.0.51</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>${maven.compiler.source}</source>
                <target>${maven.compiler.source}</target>
            </configuration>
        </plugin>
    </plugins>
</build>
</project>

And the full stack exception

Exception in thread "main" java.io.IOException: stream is closed at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOpen(HttpURLConnection.java:3366) at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3391) at com.caucho.hessian.io.Hessian2Input.readBuffer(Hessian2Input.java:2844) at com.caucho.hessian.io.Hessian2Input.read(Hessian2Input.java:2790) at com.caucho.hessian.io.Hessian2Input$ReadInputStream.read(Hessian2Input.java:2984) at java.io.InputStream.read(InputStream.java:101) at com.google.common.io.ByteStreams.copy(ByteStreams.java:70) at com.google.common.io.ByteStreams.toByteArray(ByteStreams.java:115) at w.big.data.hessian.Client.main(Client.java:20) Suppressed: java.io.IOException: stream is closed at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.ensureOpen(HttpURLConnection.java:3366) at sun.net.www.protocol.http.HttpURLConnection$HttpInputStream.read(HttpURLConnection.java:3391) at com.caucho.hessian.io.Hessian2Input.readBuffer(Hessian2Input.java:2844) at com.caucho.hessian.io.Hessian2Input.read(Hessian2Input.java:2816) at com.caucho.hessian.io.Hessian2Input.parseByte(Hessian2Input.java:2699) at com.caucho.hessian.io.Hessian2Input.access$000(Hessian2Input.java:74) at com.caucho.hessian.io.Hessian2Input$ReadInputStream.read(Hessian2Input.java:2971) at com.caucho.hessian.io.Hessian2Input$ReadInputStream.close(Hessian2Input.java:2994) at w.big.data.hessian.Client.main(Client.java:22)

willix
  • 686
  • 1
  • 6
  • 13
  • 1
    I don't have an answer, but I don't see how returning an `InputStream` in the first place would ever be a good idea for a service. – daniu Jan 10 '18 at 10:09
  • `exporter.prepare()`? In order to make the code fool proof: `getBytes(StandardCharsets.UTF_8)` and `new String(..., StandardCharsets.UTF_8)`. – Joop Eggen Jan 10 '18 at 10:13
  • @daniu well, for example, if you wanted a service that mimics a file browser, you might have a service that has one method that returns the list of file names and sizes, and one method that returns the content. The latter would be better returning an InputStream rather than a byte[] if the files are big. – willix Jan 10 '18 at 11:40

1 Answers1

0

the latest version of hessian had already solved this problem.

<!-- https://mvnrepository.com/artifact/com.caucho/hessian -->
<dependency>
    <groupId>com.caucho</groupId>
    <artifactId>hessian</artifactId>
    <version>4.0.65</version>
</dependency>

enjoy