Serialize Java 8 Stream with Jersey

How can I serialize Java 8 java.util.Stream<T> with jersey. I tried to write a MessageBodyWriter , but I need to know how to create (decorate) an existing MessageBodyWriters new MessageBodyWriter for my Stream .

 Stream<String> get(){ return some stream of strings } public <T> class StreamMessageBodyWriter<Stream<T>> implements MessageBodyWriter<Stream<T>> { public void writeTo(.......){ //How can I get the handle to MessageBodyWriter that will write for type T, //so that I can 'collect' the 'java.util.Stream<T>' and write it to //OutputStream } } 
+6
source share
2 answers

but I need to know how to create (decorate) an existing MessageBodyWriters new MessageBodyWriter for my Stream

You can simply enter Providers and use getMessagBodyWriter(...) , passing the necessary data to search for a specific author for this type. for instance

 @Provider public class StreamBodyWriter implements MessageBodyWriter<Stream> { @Context private Providers providers; @Override public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return Stream.class.isAssignableFrom(type); } @Override public long getSize(Stream stream, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) { return -1; } @Override public void writeTo(Stream stream, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException, WebApplicationException { Object obj = stream.collect(Collectors.toList()); Class<?> objType = obj.getClass(); MessageBodyWriter writer = providers.getMessageBodyWriter(objType, null, annotations, mediaType); writer.writeTo(obj, objType, null, annotations, mediaType, httpHeaders, entityStream); } } 

If you look at writeTo , I first call collect , then I get the return type. Then find the author for this type, and then just pass it on to the author.

Here is a test

 @Path("stream") public class StreamResource { @GET @Produces(MediaType.APPLICATION_JSON) public Response getStream() { List<Person> myList = Arrays.asList( new Person("Stack"), new Person("Overflow"), new Person("Sam")); Stream<Person> stream = myList.stream() .filter(p -> p.name.startsWith("S")); return Response.ok(stream).build(); } public static class Person { public String name; public Person(String name) { this.name = name; } public Person() {} } } 

C:\>curl -v http://localhost:8080/api/stream
Result:
[{"name":"Stack"},{"name":"Sam"}]

As an aside, if you plan to manipulate Stream in a writer, perhaps look at Interceptor . In fact, this will not affect, but if you want to adhere to the principle of single responsibility, Interceptor is used for this, which processes the request body.


Note: above standard JAX-RS

As an alternative...

In particular, with Jersey, you can also enter MessageBodyWorkers , for a more specific search, and even call it writeTo , which will delegate to the desired writer, if one of the exsists.

+4
source

According to the purpose of using streams (without using stream.collect(Collectors.toList()) ) there is an interesting article showing how to serialize big data from a database .

This is something like this ...

 @GET @Produces( "application/json" ) public Response streamGeneratedUuids() { return getNoCacheResponseBuilder( Response.Status.OK ).entity( new StreamingOutput() { @Override public void write( OutputStream os ) throws IOException, WebApplicationException { try (PrintWriter writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(os))) ) { //iterate the java.util.stream and write to the OutputStream writer.print("...."); } } }).build(); } 

It is not implemented using MessageBodyWriter, but can be adapted, in my opinion.

0
source

Source: https://habr.com/ru/post/984168/


All Articles